恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Java 反序列化漏洞基础:从 readObject 到命令执行

  • 首页
  • 资讯中心
  • /
  • Java 反序列化漏洞基础:从 readObject 到命令执行

相关资讯

如何高效使用BiliTools:免费B站视频下载工具终极指南 2026/7/31 12:42:35
第39讲:毕设/竞赛极速出活——整套Demo快速落地 2026/7/29 22:26:41
Soar社区贡献指南:从提交Bug到PR,新手也能参与的开源项目 2026/8/1 2:24:11

最新资讯

知识管理新命题:不是“管知识“,是“养知识“
xss靶场和upload靶场中php函数防御手段
Docker实战 :使用Docker部署OneTerm堡垒机
Python第三方库:Click
网易低代码中级认证 网易低代码CodeWave,初级认证,中级认证实操
如何利用Cloudflare Workers Next.js SaaS Template构建多租户SaaS平台

今日推荐

如何用DamaiHelper实现演唱会门票的智能自动化抢购:完整技术解决方案指南
第4篇:59 倍性能差距的索引瓶颈定位——一次教科书级的全表扫描调优
终极歌词批量下载神器:5分钟解决离线音乐库歌词同步难题

本周热门

G-Helper完整指南:免费开源工具彻底优化华硕笔记本性能
解决全部报错!OpenClaw Windows适配优化+网关修复教程
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

本月精选

如何用DamaiHelper实现演唱会门票的智能自动化抢购:完整技术解决方案指南
第4篇:59 倍性能差距的索引瓶颈定位——一次教科书级的全表扫描调优
终极歌词批量下载神器:5分钟解决离线音乐库歌词同步难题

Java 反序列化漏洞基础:从 readObject 到命令执行

发布时间:2026/8/1 19:51:27
Java 反序列化漏洞基础:从 readObject 到命令执行 Java 反序列化漏洞基础从 readObject 到命令执行写在前面前面我们复现了 Log4j2 和 fastjson 的漏洞它们都属于JNDI 注入那一挂–触发点是组件自己的特性Log4j2 的 lookup、fastjson 的 autoType最终都靠 JNDI 去加载远程类。从这篇开始我们要进入 Java 安全里另一个更底层、也更经典的话题反序列化漏洞。如果说 JNDI 注入是借组件的刀杀人那反序列化漏洞就是借 Java 自己的机制杀人–它不依赖某个特定组件的 bug而是利用 Java 反序列化机制本身的过度信任。CommonsCollections的 CC1-CC6 六条利用链就是这条路上的里程碑几乎所有 Java 安全面试、所有反序列化漏洞分析都绕不开它们。在拆解六条链之前得先把基础打牢反序列化到底是什么、为什么它能 RCE、CC 库又给我们提供了哪些积木。这篇就是那块地基。一、序列化与反序列化是什么序列化serialization把一个 Java 对象拍扁成一串字节流方便存到文件、塞进网络传输。反序列化deserialization把这串字节流再还原成一个活生生的 Java 对象。// 序列化对象 - 字节流ObjectOutputStreamoosnewObjectOutputStream(newFileOutputStream(obj.ser));oos.writeObject(someObject);// 反序列化字节流 - 对象ObjectInputStreamoisnewObjectInputStream(newFileInputStream(obj.ser));Objectobjois.readObject();不是所有对象都能序列化–它的类必须实现java.io.Serializable接口只是个标记接口没有方法。实现了它JVM 就允许这个类的对象被拍扁和还原。这功能本身很正常RPC 通信、Session 持久化、缓存存储都在用。问题出在下一步。二、readObject那个危险的魔术方法Java 的反序列化有个特殊设计当一个对象被反序列化时如果它的类自定义了readObject方法JVM 会调用这个方法而不是走默认的还原逻辑。publicclassSomeClassimplementsSerializable{privatevoidreadObject(ObjectInputStreamin)throwsIOException,ClassNotFoundException{in.defaultReadObject();// 默认还原字段// ... 然后这个类可以顺便干点别的}}注意readObject的签名是private void readObject(ObjectInputStream)它不是你主动调的而是反序列化时由 JVM 回调的。这就是所谓的魔术方法。这个设计本意是让类在反序列化时做些自定义恢复比如校验数据、重建临时字段。但副作用是只要一个对象被反序列化它所在类的readObject里的代码就会执行。而被反序列化这个动作在很多场景下是由外部数据触发的–比如服务端读取客户端传来的序列化字节流。于是攻击面就出现了攻击者递交一段精心构造的字节流服务端一调用readObject字节流里指定的那个类的readObject方法就会执行–而那个类的readObject里可能藏着危险操作。这就是反序列化漏洞的本质反序列化 攻击者能触发任意可序列化类的 readObject 执行。三、漏洞利用的两步法光让某个类的readObject执行还不够–那个类的readObject里得有能通往命令执行的逻辑。但显然 JDK 不会蠢到在readObject里直接Runtime.exec。真实的利用是搭桥找一个readObject里会调用某个对象方法的类再把这个方法调用一步步导到Runtime.exec或加载字节码上。这就是经典的两步法┌─────────────────────────────┐ ┌──────────────────────────┐ │ ① 入口类反序列化入口 │ │ ② 执行体最终干坏事 │ │ │ │ │ │ 它的 readObject 会在反序列化 │ ──── │ Runtime.exec(calc) │ │ 时调用某个对象的方法 │ 桥 │ 或 加载恶意字节码 │ │ (get / hashCode / toString / │ │ │ │ compare / setValue ...) │ │ │ └─────────────────────────────┘ └──────────────────────────┘入口类readObject里调用了某个对象的方法get、hashCode、toString、compare、setValue等。因为被调用的对象是攻击者可控的在字节流里指定所以这个方法调用可以被引向攻击者放好的对象。执行体一段能把方法被调用转换成命令执行的逻辑。中间用各种触发器Map、Comparator 等把方法调用一层层传到执行体。CC 链里的各种类要么是入口要么是触发器要么是执行体。四、CommonsCollections 的核心积木org.apache.commons.collectionsCC 库是 Apache 的集合工具库曾经几乎是 Java 项目的标配。它恰好提供了一组完美的积木来拼反序列化攻击。下面这些类是 CC1-CC6 反复出场的角色先认个脸熟。4.1 Transformer 三件套执行体的核心Transformer是一个变换器接口输入一个对象输出一个对象。publicinterfaceTransformer{Objecttransform(Objectinput);}CC 库提供了三个关键实现能拼出执行任意命令的逻辑①ConstantTransformer–无论输入啥恒返回构造时传入的常量。newConstantTransformer(Runtime.class).transform(任意输入)// 永远返回 Runtime.class②InvokerTransformer–反射调用输入对象的任意方法最危险的一个。// transform 时等价于input.methodName(paramTypes, args)newInvokerTransformer(exec,newClass[]{String.class},newObject[]{calc}).transform(runtimeInstance)// - runtimeInstance.exec(calc)③ChainedTransformer–把多个 Transformer 串起来前一个的输出当后一个的输入。newChainedTransformer(newTransformer[]{newConstantTransformer(Runtime.class),// - Runtime.classnewInvokerTransformer(getMethod,...),// - Method getRuntimenewInvokerTransformer(invoke,...),// - Runtime 实例newInvokerTransformer(exec,...)// - runtime.exec(calc)})为什么这么绕因为InvokerTransformer.transform是对输入对象调方法而Runtime.getRuntime()是静态方法、没法当实例方法调。所以要先拿Runtime.class再反射getMethod(getRuntime)再invoke(null)拿到实例最后exec。一条绕弯的反射链。这三件套串起来 任意命令执行。现在只差让ChainedTransformer.transform被调用。4.2 触发器LazyMap 与 TransformedMapCC 库有两种 Map能在正常操作时触发TransformerLazyMap–get(key)时若 key 不存在用factory.transform(key)生成 value 并缓存。factory就是上面那个ChainedTransformer。MaplazyMapLazyMap.decorate(innerMap,chainedTransformer);lazyMap.get(不存在的key);// - chainedTransformer.transform(不存在的key) - Runtime.execTransformedMap–put/setValue时对 value 跑valueTransformer.transform。CC1/CC3/CC5/CC6 都用LazyMap作为触发器。所以剩下的问题就是怎么让LazyMap.get()在反序列化时被调用4.3 桥接类TiedMapEntryTiedMapEntry持有一个Map和一个key它的三个方法都指向getValue()TiedMapEntry.hashCode()-getValue()-map.get(key)TiedMapEntry.toString()-getValue()-map.get(key)如果map是LazyMap那么TiedMapEntry.hashCode()或toString()一被调用就会触发LazyMap.get()-ChainedTransformer.transform()。这一下把入口拓宽了任何在反序列化时会调用hashCode()或toString()的类都能借TiedMapEntry桥接到LazyMap。CC5借toString、CC6借hashCode就是走这条路。4.4 字节码执行体TemplatesImplChainedTransformerRuntime.exec这条路有个软肋很多防护黑名单、RASP会盯着Runtime、InvokerTransformer。于是有了更隐蔽的执行体直接加载恶意字节码。com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl是 JDK 内置的 XSLT 模板类。它有个_bytecodes字段存着一段 Java class 字节码。调用它的newTransformer()/getOutputProperties()时会走newTransformer() - getTransletInstance() - defineTransletClasses() // defineClass 加载 _bytecodes - newInstance() // 实例化那个恶意类恶意类继承AbstractTranslet在静态初始化块里执行命令publicclassEvilextendsAbstractTranslet{static{Runtime.getRuntime().exec(calc);// 类被加载时执行}// 两个 transform 空实现父类抽象方法}这条路的好处它加载的是任意字节码不是固定的Runtime.exec绕过针对 Runtime 的黑名单。CC2/CC3/CC4 都用它当执行体。五、六条链的全景预告把上面的积木组合起来就得到了 CC1-CC6。它们本质上是两个维度的组合入口线执行体线CC1 / CC3AnnotationInvocationHandler受 JDK 8u71 限制CC1RuntimeCC3TemplatesImplCC2 / CC4PriorityQueue需 CC4 库CC2TemplatesImplCC4TemplatesImplCC5 / CC6BadAttributeValueExpException/HashSet通用不受 8u71 限制都是 Runtime入口线演进从依赖 JDK 内部类CC1/3被 8u71 修掉- 借PriorityQueueCC2/4要 CC4 库- 借BadAttributeValueExpException/HashSetCC5/6通用。执行体线演进ChainedTransformerRuntimeCC1/5/6-TemplatesImpl字节码CC2/3/4绕黑名单。记住这两个维度后面六条链就不是六个孤立的东西而是 2×3 的组合。接下来我们就一条一条拆开看每条链都配真实复现calc 弹出 RCE。参考ysoserialCC 链的出处https://github.com/frohoff/ysoserialApache Commons Collectionshttps://commons.apache.org/proper/commons-collections/Java 反序列化漏洞科普https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号