WEB通用漏洞-反序列化

WEB通用漏洞-反序列化

前置知识

序列化/反序列化

序列化:对象/数组转换为字符串的格式(二进制数据流)。

反序列化:将字符串格式转换成对象/数组。

对象/数组序列化的作用:保存当前对象/数组的状态(确保状态不丢失),便于进行对象/数组的存储和传输(提高对象/数组的持久性)。

以php为例,序列化函数和反序列化函数

serialize()    // 序列化
unserialize()  // 反序列化

img

魔术方法

魔术方法是计算机编程中的一个概念,用于描述如何在特定条件下自动执行某些代码或操作(例如:构造函数、析构函数等)。

在PHP中,魔术方法常用__开头

常见的反序列化函数

img

PHP反序列化

原理

未对用户输入的反序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行、SQL注入、目录遍历等不可控后果。在反序列化的过程中自动触发了某些魔术方法,当进行反序列化的时候就有可能会触发对象中的一些魔术方法。

换句话说:攻击者可以自由控制反序列化字符串(指的是反序列化函数接收一个变量,而该变量可由攻击者控制),构造payload,修改对象的状态,当payload被反序列化时,会生成一个恶意对象,当调用该对象的方法时(有可能会调用魔术方法),就会造成攻击。

反序列化漏洞一般黑盒探测不到,都是在白盒下进行测试(直接寻找特定函数即可)。

反序列化的利用

  • 魔术方法的调用逻辑(如触发条件)
  • 语言原生类的调用逻辑(如SoapClient)
  • 语言自身的安全缺陷(如CVE-2016-7124)

PHP常用的魔术方法

img

注:__CALL魔术方法:调用某个方法,若方法存在,则直接调用,若不存在,则会去调用__CALL函数

注:__GET魔术方法:读取一个对象的属性时,若属性存在,则直接返回属性值,若不存在,则会调用__get函数

注:__SET魔术方法:设置一个对象的属性时,若属性存在,则直接赋值,若不存在,则会调用__set函数

注:__SLEEP魔术方法:serialize之前被调用,可以指定要序列化的对象属性

注:__WAKEUP魔术方法:反序列化恢复对象之前调用该方法

注:__ISSET魔术方法:检测对象的某个属性是否存在时执行此方法。当对不可访问属性调用isset()或empty()时,会调用__isset方法。

注:__UNSET魔术方法:在不可访问的属性上使用unset()时触发,销毁对象的某个属性时执行该函数。

注:值得注意的是:unset()函数不光可以销毁属性,更可以销毁对象

注:__INVOKE魔术方法:将对象当作函数来使用时执行此方法,通常不推荐这样做

对象属性权限

  • public:在本类内部、外部类、子类都可以访问。
  • protect:只有本类或子类或父类中可以访问
  • private:只有本类内可以使用

这些权限在序列化的时候,数据显示有些差别:

private属性序列化的时候格式是%00类名%00成员名,%00不会显示,但是长度为1。

protect属性序列化的时候格式是%00*%00成员名。

注:这种特性使得:在构造payload的时候,除特殊情况外,一般都要将payload进行base64编码,如果不进行base64编码的话,诸如%00这样的字符是会被忽略,从而导致payload不正确的情况

PHP序列化/反序列化字符串分析

假设存在类demotest

class demotest{
    public $name = 'xiaodi';
    public $sex = 'man';
    public $age = '29';
}

当对上述类的对象进行序列化后,序列化字符串为:

O:8:"demotest":3:{s:4:"name";s:6:"xiaodi";s:3:"sex";s:3:"man";s:3:"age";s:2:"29";}

解读:

  • O标识Object,8表示类名长度,demotest为类名
  • 3表示有三个成员
  • s:4:"name";s:6:"xiaodi"; 代表:有一个string类型的成员名长度为4的成员,名字是name。这个成员有一个string类型的,长度为6的值,叫xiaodi。
  • s:3:"sex";s:3:"man"; 代表:有一个string类型的成员名长度为3的成员,名字是sex。这个成员有一个string类型的,长度为3的值,叫man。
  • s:3:"age";s:2:"29"; 代表:有一个string类型的成员名长度为3的成员,名字是age。这个成员有一个string类型的,长度为2的值,叫'29'。

当对上述类的对象进行反序列化后,序列化字符串为:

object(demotest)#2 (3) { ["name"]=> string(6) "xiaodi" ["sex"]=> string(3) "man" ["age"]=> string(2) "29" }

注:在上述的序列化字符串中我们可以看到:字符串中没有记录任何方法和魔术方法的信息,因此当我们进行构造payload的时候,可控点只有变量,方法是不可控的

注:换句话来说:在php反序列化的过程中,可控点只有变量,方法不可控

POP链构造

见CTF-Show-反序列化系列

原生类反序列化

见CTF-Show-反序列化系列、BUUCTF-极客大挑战2019-PHP

文章:

如果在代码审计中存在反序列化的点,但是在原本的代码中找不到可利用的类时,可以考虑使用php中的一些原生类(php内部自带的类)。

有些原生类不一定能够进行反序列化,php中使用了zend_class_unserialize_deny来禁止一些类的反序列化。

我们可以通过脚本获取php中所有的原生类:

 <?php
$classes = get_declared_classes();
foreach ($classes as $class) {
    $methods = get_class_methods($class);
    foreach ($methods as $method) {
        if (in_array($method, array(
            '__destruct',
            '__toString',
            '__wakeup',
            '__call',
            '__callStatic',
            '__get',
            '__set',
            '__isset',
            '__unset',
            '__invoke',
            '__set_state'    // 可以根据题目环境将指定的方法添加进来, 来遍历存在指定方法的原生类
        ))) {
            print $class . '::' . $method . "\n";
        }
    }
    
}

Java反序列化

原理

跟PHP相似,如果攻击者可以自由的控制序列化后的字符串,那么在进行反序列化后,调用恶意对象时就会造成攻击。

Java反序列化所产生的地方

反序列化操作一般应用在导入模板文件、网络通信、数据传输、日志格式化存储、对象存储在磁盘或数据库存储等业务场景。因此,审计过程中要重点关注这些业务。

具体细节:

img

Java序列化/反序列化字符串特征

一段数据以rO0AB开头,你基本可以确定这串就是JAVA序列化BASE64加密的数据。或者如果以aced开头,那么他就是这一段JAVA序列化的16进制。

最好通过诸如c32asm这样的工具去查看。

Java反序列化字符串构造/利用

通过ysoserial、GUI_TOOLS等工具,来进行构造,具体使用方法,请参考官方手册。

ysoserial:https://github.com/frohoff/ysoserial

具体的案例,可以参考Webgoat专题。

Java序列化/反序列化字符串分析

我们可以使用诸如SerializationDumper这类的工具,来对Java反序列化字符串进行分析。

这个工具经常用来分析Payload的构造。

SerializationDumper:https://github.com/NickstaDB/SerializationDumper/tree/master

黑盒/白盒测试

  • 黑盒:从常见的功能点上观察,看交互的数据是否满足Java反序列化字符串的格式。
  • 白盒:第三方插件安全(利用已知的第三方插件的漏洞)& Java特定反序列化函数搜索 & 找应用的特定功能

Python反序列化

原理

跟PHP相似,如果攻击者可以自由的控制序列化后的字符串,那么在进行反序列化后,调用恶意对象时就会造成攻击。

反序列化函数

img

注:除了这些函数之外,还有:marshal、PyYAML、shelve、PIL、unzip

魔术方法

img

POP链构造

见BUUCTF-CISCN2019华北赛区-ikun

注:与php反序列化不同,python反序列化POP链可以任意构造,可控点不只是变量,方法,类都可以。

注:如果存在漏洞的服务器,python版本是A,那么你在构造POP链的时候,使用的Python版本也得是A,一定要对应起来。

自动化审计工具bandit

对于python反序列化漏洞,在白盒测试的时候,我们可以搜索特定函数关键字,来进行审计。

黑盒测试一般测不到此漏洞。

或者,我们也可以使用工具来进行审计。

bandit的文档:https://bandit.readthedocs.io/en/latest/

安装bandit

pip install bandit

img

致谢

https://www.bilibili.com/video/BV1pQ4y1s7kH/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click

免责声明

    本博客中的内容仅供学习之用,不用于商业用途,也不可以用于任何非法用途,否则后果自负,本人不承担任何责任!
posted @   夏目^_^  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示