PHP反序列化漏洞(unseriliaze)
什么是PHP反序列化漏洞
php序列化的函数为 serialize ,可以将对象中的成员变量转换成字符串。 反序列化的函数为 unserilize ,可以将 serialize 生成的字符串重新还原为对象中的成员变量。 将用户可控的数据进行了反序列化,就是PHP反序列化漏洞
简单来说,就是我们可以控制unserialize(a)
这个函数接收的参数a
,比如通过GET
或POST接收参数a
,我们可以通过伪造自己的序列化后的恶意代码(通过修改程序原有的魔术方法属性),然后让unserialize()这个函数去反序列化我们构造的恶意代码,从而达到执行的效果。
基础知识:序列化的属性权限问题
php在使用serialize()的时候产生的数据会根据attribute的权限不同,产生不同的数据和长度。
private类型
1 |
|
观察发现打出来的结果是:O:4:"test":1:{s:10:"testflag";s:6:"Active";}
此处代表属性名的testflag长度实际只有8,为什么却打出来有10个呢。这是因为他生成的格式是==%00类名%00属性名==
protected类型
生成格式为==%00*%00属性名==
public类型
生成格式直接为==属性名==
基础知识:魔法方法
construct()
对象创建时调用,但**unserialize()**不会调用
wakeup()
在unserialize()的时候会自动调用
destruct()
当对象被销毁的时候会被调用
toString()
当反序列化后的对象被输出在模版的时候会被调用
(1)echo (
$obj
) / print($obj
) 打印时会触发(2)反序列化对象与字符串连接时
(3)反序列化对象参与格式化字符串时
(4)反序列化对象与字符串进行 == 比较时(PHP进行 == 比较的时候会转换参数类型)
(5)反序列化对象参与格式化SQL语句,绑定参数时
(6)反序列化对象在经过php字符串函数,如 strlen()、addslashes()时
(7)在in_array()方法中,第一个参数是反序列化对象,第二个参数的数组中有toString返回的字符串的时候toString会被调用
(8)反序列化的对象作为 class_exists() 的参数的时候
get()
当从不可访问的属性读取数据时调用
call()
当在对象上下文中调用不可访问的方法时触发
基础知识:PHP反序列化利用条件
- 当前作用域必须要有该Class存在
- 序列化之序列化属性,不序列化Method,所以我们只能控制Attribute
- 在写payload的时候,我们只写与属性有关的内容,若涉及到方法,该方法也需要在原始的漏洞代码中存在。
PHP反序列化进阶:Phar反序列化漏洞
什么是Phar
在软件中,PHAR(PHP归档)文件是一种打包格式,通过将许多PHP代码文件和其他资源(例如图像,样式表等)捆绑到一个归档文件中来实现应用程序和库的分发。[来源于wiki]
phar组成结构
stub
phar文件的标志,格式为xxx<?php xxx; __HALT_COMPILER();?>;
xxx可以为任何内容,所以我们可以伪造图片来绕过上传限制
manifest
以序列化形式储存,含压缩文件属性等信息
当文件操作函数通过phar://伪协议来解析phar文件的时候就会将数据反序列化,所以我们可以利用系统文件操作函数来反序列化。
contents
压缩文件的内容
signature
签名,在文件的末尾
利用条件
文件上传点 - phar文件能够上传到服务端
有系统文件操作函数,且
:
、/
、phar
等特殊字符未被过滤。只要是函数的实现过程间接或直接调用了php_stream_open_wrapper都可能触发phar反序列化漏洞
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16exif_thumbnail
exif_imagetype
imageloadfont
imagecreatefrom***
hash_hmac_file
hash_file
hash_update_file
md5_file
sha1_file
get_meta_tags
get_headers
getimagesize
getimagesizefromstring
$zip = new ZipArchive();
$res = $zip->open('c.zip');
$zip->extractTo('phar://test.phar/test');除了以上还有很多函数可能触发,更多的参见另一位师父的关于phar反序列化的文章
有可用的魔术方法作为跳板
phar:// 伪协议
如何生成一个phar文件?
windows首先将php.ini里面的phar.readonly
设为off,并把最前面的注释符去掉
在网上看见有师父提到linux环境下:
如果是linux环境下,需要在 /etc/php/7.0/apache2/php.ini 和/etc/php/7.0/cli/php.ini 这两个文件都需要修改 phar.readonly 否则不能生成phar文件
我本人用的是mac系统,在etc/private/php.ini直接修改即可。
1 |
|
踩了一个坑:
代码写好后,有一个坑,就是我直接运行浏览器运行php是不行的(提示500错误),研究以后猜测是权限问题,因为我的网站是搭建在library目录下的,后来改用命令行在vscode
里运行提示也permission denied
,加上sudo
就好了。
phar反序列化漏洞利用实例
漏洞代码:
1 |
|
POC:
1 |
|
实现:在get请求中采用phar://你的文件.phar的格式,成功执行代码