0%

PHP反序列化

PHP中的反序列化漏洞

可能利用反序列化的提示

代码中出现file_get_content等文件操作相关函数
unserialzeserialze等危险函数
类中存在__wakeup__toString__call__sleep等魔法方法
这时输入若可控,即可构造序列化数据,在反序列化过程中执行函数,控制文件读取,拿到flag

且__construct()函数只在对象创建(new)时会自动调用,但在 unserialize() 时是不会自动调用的

__wakeup函数绕过

要求:PHP5 < 5.6.25, PHP7 < 7.0.10
__wakeup()函数在序列化对象被反序列化时调用,如果此时序列化数据显示的数据个数与实际数据个数不符,即可跳过对__wakeup()函数的调用
如:O:3:"Stu":2:{s:4:"name";s:3:"lzx";}此时的Stu类只有一个名为lzx的数据name,但序列化数据显示该类拥有两个数据,即可引发错误跳过对__wakeup()函数的执行

不同对象的反序列化

不同对象反序列化时起键名将会发生改变,就public对象而言,protected对象在反序列化时,其键名会变为%00\*%00key,而private对象为%00classname%00key,%00为url编码的字符

字符逃逸漏洞

序列化数据经过某些过滤后数据长度发生改变,使得可控字符串逃逸出来反序列化收到控制

字符增加导致逃逸

讲解背景为0ctf2016的piapiapia
首先,我们可以通过凭借数据的方法改变序列化内容
例如现在有序列化内容O:3:"Stu":2:{s:4:"name";s:3:"lzx";s:4:"data";s:3:"abc";}
我们只能控制name变量,但也可以以此修改data 的内容,比如我们令name=lzx";s:4:"data";s:6:"hacker";}
此处name在序列化时会被认为长度是30
这样子我们的数据就变为了{s:4:"name";s:30:"lzx";s:4:"data";s:6:"hacker";}";s:4:"data";s:3:"abc";}
在序列化过程中,后面多余的数据会被舍弃
但这里还有一个问题,当描述数据长度的数与数据长度不一致时,会导致反序列化失败
但是本题拥有一个特殊环境,它将SQL注入相关的语句如select,insert,where等语句统一替换成了hacker,这里从where到hacker使得整体的字符多出了一个,这意味着我们每输入一个where就使得我们可控字符增加一个。
所以当我们输入一定数量的where时,增加出来的字符就会填补上我们原来自己注入字符所占用的位置,完成反序列化的操作,而后面的真实数据则被我们抛弃,完成了对数据的篡改

字符减少导致逃逸

题目为安洵杯 2019 easy_serialize_php,本题将flag,PHP等字眼替换为空,利用extract($_POST);进行变量覆盖,控制变量进行反序列化,这里有两种控制方法
正常反序列化字符串为a:3:{s:4:"user";s:5:"guest";s:8:"function";s:4:"test";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
可以同时控制guest和function的值,使得guest的值将function的键部分吃掉,使function的值逃逸出来,覆盖img
也可重新添加一对键值,通过键名吃掉值的部分,使得部分构造好的值逃逸,覆盖后续的img

ps

这里有一个坑,他使用extract($_POST);解析变量,需要我发包时的content-type为application/x-www-form-encoded,不然没得用

参考链接

https://www.cnblogs.com/wangtanzhi/p/12261610.html

phar反序列化漏洞

发生在php中存在的文件操作函数参数可控,将打包的phar包改为任意后缀上传并以phar协议读取即可
phar被正则开头匹配禁止的场合可以使用php://filter/resource=phar://进行绕过
finfo_file/finfo_buffer/mime_content_type这些函数均可通过phar协议触发反序列化,因此看到这些函数的时候就可以考虑这个方法了

这里注意构造数据时数据类型要与原来的数据类型完全一致,不能说名字相同反序列化就能成功。public和private反序列化后private多一个不可见字符。并且原来的array之类的变量都要进行初始化,做好代码审计工作

例题有bytectf的ezcms
贴一个Zedd师傅的文章https://xz.aliyun.com/t/6057

phar反序列化影响的函数

fileatime / filectime / filemtime stat / fileinode / fileowner / filegroup / fileperms
file / file_get_contents / readfile / fopen
file_exists / is_dir / is_executable / is_file / is_link / is_readable / is_writeable / is_writable parse_ini_file
unlink copy`
有关文件的操作基本都被涉及,在这些函数下使用phar://协议对文件进行访问均可触发我们先前构造好的数据进行巧妙的攻击

phar反序列化数据的构造

$a = new File('123','456'); //构建一个设计好数据的变量
//echo unserialize($a);
$phar = new Phar("1.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub,需要绕过图片检测时可在前面加GIF23a
$phar->setMetadata($a); //将自定义的meta-data存入manifest
$phar->addFromString("1.txt", "test"); //添加要压缩的文件,内容无意义
//签名自动计算
$phar->stopBuffering();
例题为bytectf的ezcms