反序列化任意代码执行漏洞

 人参与 | 时间:2026-10-17 06:51:55

2015年,反序Java反序列化漏洞在WebLogic上被大规模利用时,列化漏洞很多团队的任意第一反应是“我们没传什么奇怪的东西”。问题恰恰出在这——攻击者根本不需要你传什么奇怪的代码东西,他们只需要你传了一个会被ObjectInputStream.readObject()吃掉的执行数据。

反序列化漏洞的反序本质,是列化漏洞把数据还原成对象的过程中,程序信任了不该信任的任意输入。序列化本身是代码个好东西,把对象拍扁成字节流,执行方便传输和存储。反序但反序列化是列化漏洞反向操作,它要根据字节流里的任意类描述符去加载类、调用构造方法、代码触发readObject或readResolve。执行如果这条链路上有某个类的readObject方法恰好做了危险操作,比如执行命令、加载远程类,攻击者就能通过构造恶意字节流,让服务端自己把恶意代码跑起来。

Apache Commons Collections那个著名的利用链就是典型。它本身是个工具库,很多Java应用都依赖它。攻击者发现InvokerTransformer可以反射调用任意方法,配合ChainedTransformer就能拼出一条从readObject到Runtime.exec的完整路径。WebLogic、JBoss、Jenkins都中过招。更麻烦的是,这条链不依赖目标应用自己写什么代码,只要classpath里有这个库就行。

PHP那边是另一种画风。unserialize()遇到__wakeup()或__destruct()魔术方法时,如果类属性可控,攻击者就能控制对象内部状态,进而操纵后续逻辑。Typo3、Magento、Laravel都出过这类漏洞。Python的pickle也类似,__reduce__方法可以直接返回一个可调用对象和参数,反序列化时自动执行。很多机器学习模型文件用pickle存,加载模型等于执行代码,这个坑到现在还有人在踩。

防御这事,说来说去就几条路。最彻底的是别用原生反序列化,换成JSON、Protobuf这类纯数据格式。如果非用不可,就上白名单——Java里可以用ObjectInputFilter限制允许反序列化的类,PHP里可以用allowed_classes参数。但白名单维护起来很烦,业务一迭代就可能漏掉新类。还有一种思路是加签名,序列化数据带HMAC,服务端先验签再反序列化。这能挡住外部攻击,但挡不住内网横向移动——攻击者拿到密钥就全废了。

我见过一些团队的处理方式很拧巴。他们知道有漏洞,但老系统动不了,就在WAF上加规则拦java -jar、bash -i这类关键词。这基本是心理安慰,因为利用链可以编码、可以分片、可以用DNS外带数据。真正有效的还是升级依赖库、打补丁、关掉不必要的端口。WebLogic那个洞,Oracle发了补丁,但很多企业拖了半年才打,中间被挖矿团伙扫了个遍。

反序列化漏洞的教训其实不在技术层面。它暴露的是“信任边界”的模糊——开发者觉得内部服务之间传的数据是可信的,觉得序列化框架会处理好一切。但攻击者恰恰从这些“觉得”里找缝隙。一个字节流从网络进来,不管它来自哪里,在反序列化之前都只是一串不可信的数据。这个认知不建立起来,换什么框架都白搭。

顶: 9踩: 541