千家信息网

怎么解析Java反序列化漏洞

发表于:2026-10-31 作者:千家信息网编辑
千家信息网最后更新 2026年10月31日,怎么解析Java反序列化漏洞,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。一、基本概念Java序列化:就是将内存中的Ja
千家信息网最后更新 2026年10月31日怎么解析Java反序列化漏洞

怎么解析Java反序列化漏洞,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

一、基本概念

Java序列化:就是将内存中的Java对象转换为字节序列的过程,可以理解为对Java对象打个快照。通过序列化,可以方便将Java对象保存在内存、文件、数据库等媒介中,也便于在网络中传输和共享Java对象。

Java反序列化:就是Java序列化的逆过程,将字节序列恢复为Java对象的过程。

序列化/反序列化并不是Java语言的独有特性,像PHP、Python、Ruby等动态语言也有类似的特性。序列化/反序列化的主要目的是:

1、远程过程调用(RPC):为不同系统或不同进程之间提供Java对象数据交互;

2、缓存/持久化存储:可以将Java对象缓存或存储到本地文件、磁盘、数据库等媒介中;

3、会话tokens:用于HTTP cookies、HTML form表单参数、API 认证tokens等场景的交互数据。

在Java中,序列化/反序列化操作主要由 java.io.ObjectOutputStream.writeObject(Object) 方法和 java.io.ObjectInputStream.readObject()方法实现;在用户代码中,可以通过重写上述方法实现自定义操作。

Java序列化数据格式

参考文档:https://docs.oracle.com/javase/8/docs/platform/serialization/spec/protocol.html

Java对象经过序列化后得到的数据是个二进制流,以固定的魔数(0xaced)和版本(0x0005)开始;在渗透测试过程中,可以以此来识别应用系统中反序列化的入口点。(0xaced 0005的base64编码以rO0AB开始,通常在Web应用系统中传输的Java序列化数据会经过base64编码)。

Java序列化数据示例:

00000000: aced 0005 7400 0d48 656c 6c6f 2c20 776f  ....t..Hello, wo00000010: 726c 6421                                rld!

在Github上提供了Java对象序列化dump工具,可以对Java对象序列化后的数据进行解析,具体请参考:https://github.com/NickstaDB/SerializationDumper。例如,将上述二进制数据解析后的结果如下:

二、漏洞原理

Java反序列化漏洞产生的原因在于Java应用程序接收来自用户的序列化数据并尝试对其进行反序列化;如果攻击者通过构造恶意输入,让反序列化过程产生非预期的对象,将可能导致各种后果,严重时可能造成远程代码执行。

Java序列化/反序列化代码demo

下面代码演示将一段字符串经序列化保存到本地文件中,然后再从文件中恢复序列化的字符串。

package orz.vuln.poc;import java.io.FileOutputStream;import java.io.ObjectOutputStream;//将String对象序列化后保存到data.ser文件中public class Serialization {    public static void main(String[] args) throws Exception {        String text = "Hello, world!";                FileOutputStream fos = new FileOutputStream("D:/data.ser");        ObjectOutputStream oos = new ObjectOutputStream(fos);        oos.writeObject(text);        oos.close();        fos.close();    }}

序列化后的数据:

package orz.vuln.poc;import java.io.FileInputStream;import java.io.ObjectInputStream;//将data.ser文件中的数据反序列化为Java对象:public class Deserialization {    public static void main(String[] args) throws Exception {        FileInputStream fis = new FileInputStream("D:/data.ser");        ObjectInputStream ois = new ObjectInputStream(fis);        String text = (String) ois.readObject();        fis.close();        ois.close();        System.out.println(text);    }}

执行结果:

在这里,可以通过修改本地文件数据控制反序列化后的字符串的值;例如,将data.ser修改如下:

00000000: aced 0005 7400 0845 7669 6c54 6578 74    ....t..EvilText

执行反序列化代码,结果:

更进一步Java序列化/反序列化

在实际开发中,更多是通过实现Serializable接口并重写readObject()方法对自定义类对象进行反序列化,以完成更多操作。如下代码示例,我们通过自定义Test类,实现了Serializable接口,并重写readObject()方法,在readObject()方法中,我们自定义输出字符串"Oops..."和弹出计算器操作。

package orz.vuln.poc;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;public class DemoCode {        public static void main(String[] args) throws Exception {                                Test test = new Test("calc.exe");                                FileOutputStream fos = new FileOutputStream("D:/object.ser");                ObjectOutputStream oos = new ObjectOutputStream(fos);                oos.writeObject(test);                oos.close();                fos.close();                                FileInputStream fis = new FileInputStream("D:/object.ser");                ObjectInputStream ois = new ObjectInputStream(fis);                Test test2 = (Test) ois.readObject();                ois.close();        }}class Test implements Serializable {        private String cmd;                public Test(String cmd) {                this.cmd = cmd;        }                //重写readObject()方法        private void readObject(java.io.ObjectInputStream in) throws Exception {                in.defaultReadObject();                System.out.println("Oops...");                java.lang.Runtime.getRuntime().exec(cmd);//触发代码执行,模拟调用链        }}

执行结果:

调用堆栈如下:

DemoCode [Java Application]           orz.vuln.poc.DemoCode at localhost:53445                      Thread [main] (Suspended (entry into method exec in Runtime))                           Runtime.exec(String) line: 345                                Test.readObject(ObjectInputStream) line: 38                           NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]                               NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57                               DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43                           Method.invoke(Object, Object...) line: 601                               ObjectStreamClass.invokeReadObject(Object, ObjectInputStream) line: 1004                         ObjectInputStream.readSerialData(Object, ObjectStreamClass) line: 1891                           ObjectInputStream.readOrdinaryObject(boolean) line: 1796                              ObjectInputStream.readObject0(boolean) line: 1348                             ObjectInputStream.readObject() line: 370                              DemoCode.main(String[]) line: 22              D:\Tools\Java\jdk1.7.0_21\jre\bin\javaw.exe (2021年3月17日 下午5:13:24)    

从上述结果可以看出,反序列化将调用重写的readObject()方法,执行了自定义的字符串输出和弹出计算器。如果重写的readObject()方法中可以构造出代码执行利用链,将存在远程代码执行漏洞。当然,在实际开发过程中不可能像上述代码一样直接在readObject()方法内部写上java.lang.Runtime.getRuntime().exec(cmd)这种代码;但是也差不太多,只是实际调用链比较复杂,通过控制反序列化的输入数据,结合Java反射调用机制,寻找可构建远程代码执行的调用链,动态调用java.lang.Runtime.getRuntime().exec()完成代码执行。

下面可以放一个JDK7u21反序列化漏洞的调用堆栈做个对比,只是调用过程更加复杂化:

orz.vuln.poc.JDK7u21Exploit at localhost:53452            Thread [main] (Suspended (entry into method exec in Runtime))                   owns: TemplatesImpl  (id=46)                     Runtime.exec(String) line: 345                        EvilCodes.() line: 17                     NativeConstructorAccessorImpl.newInstance0(Constructor, Object[]) line: not available [native method]                     NativeConstructorAccessorImpl.newInstance(Object[]) line: 57                  DelegatingConstructorAccessorImpl.newInstance(Object[]) line: 45                      Constructor.newInstance(Object...) line: 525                 Class.newInstance0() line: 374                       Class.newInstance() line: 327                        TemplatesImpl.getTransletInstance() line: 380                 TemplatesImpl.newTransformer() line: 410                      NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]                       NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57                       DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43                   Method.invoke(Object, Object...) line: 601                       AnnotationInvocationHandler.equalsImpl(Object) line: 197                      AnnotationInvocationHandler.invoke(Object, Method, Object[]) line: 59                       $Proxy0.equals(Object) line: not available                       LinkedHashMap(HashMap).put(K, V) line: 475                 LinkedHashSet(HashSet).readObject(ObjectInputStream) line: 309                      NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]                       NativeMethodAccessorImpl.invoke(Object, Object[]) line: 57                       DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 43                   Method.invoke(Object, Object...) line: 601                       ObjectStreamClass.invokeReadObject(Object, ObjectInputStream) line: 1004                 ObjectInputStream.readSerialData(Object, ObjectStreamClass) line: 1891                   ObjectInputStream.readOrdinaryObject(boolean) line: 1796                      ObjectInputStream.readObject0(boolean) line: 1348                     ObjectInputStream.readObject() line: 370                      JDK7u21Exploit.main(String[]) line: 91        

三、总结

Java反序列化漏洞的根源在于ObjectInputStream.readObject()方法在进行反序列化时并没有对生成的对象类型做检测和限制,并且当这种反序列化漏洞存在于一些公共类库中时,将造成重大影响。例如Apache Commons Collections中实现的一些类可以被反序列化用来实现任意代码执行。而在WebLogic、WebSphere、JBoss、Jenkins、OpenNMS这些应用的反序列化漏洞能够得以利用,就是因为这些应用中使用了Apache Commons Collections类库。这就好像在开启了ASLR地址随机化防御的系统中,出现了一个加载地址固定的共享库,或者类似于C语言中使用的链接库,当这些库存在漏洞时,将对使用了这些库的应用造成重大影响。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。

序列 对象 数据 代码 方法 漏洞 过程 文件 应用 字符 字符串 结果 系统 实际 就是 更多 语言 不同 复杂 重大 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 手冲咖啡和咖啡机区别 保险科技 互联网保险 科技互联网企业 深圳恒合互联网络科技有限公司 鸠鸠互联网科技 互联网科技公司电话 有马互联网科技 有木互联网科技 深圳天众互联网科技公司 互联网 新科技 美国互联网前沿科技 滨湖区互联网智能科技产品供应 知域互联网科技有限公司大骗子 互联网5g黑科技有哪些 互联网科技大赛获奖感言 本届互联网大会上的黑科技 宁波跨境商互联网科技有限公司 普陀区互联网教育科技管理办法 亚光科技低轨卫星互联网 山东亿川互联网科技有限责任公司 善班互联网科技有限公司 太原新华互联网科技学校怎么样 互联网科技公司招聘 互联网汽车科技小镇 赶超互联网科技 微信多开 九思连强互联网电子科技有限公司 银川新华互联网科技学校是国营吗 科技和互联网行业的特点 互联网科技创业计划的风险分析 山东亿川互联网科技有限责任公司
0