كنز FortiGate SSL-VPN الذهبي. CVE-2024-21762 وCVE-2023-27997. 79 عميل استغلال يعمل. 53 طراز أجهزة. 55 إصدار FortiOS.
أرشيف بحثي. تم استردادها كما وُجدت. لم أكتب هذه الملفات.
تاريخ النشر: 1 سبتمبر 2026
هذا المستودع هو المنسّق (orchestrator)، والحمولات من المرحلة الثانية، ومستمعات المشغّل (operator listeners) التي تقع فوق كتالوج استغلال FortiGate SSL-VPN الخاص بكل طراز (SKU). القصة الكاملة، والأعداد، وملاحظات الصيد موجودة في السلسلة The SSL-VPN pot of gold على Abraxas Labs.
لا تشغّل هذه المواد ضد أي مضيف إلا إذا كان لديك إذن كتابي صريح من كل من الطرف المستضيف لهذا المستودع ومالك الأنظمة المستهدفة. كانت ثغرات CVE ذات الصلة عامة وتم تصحيحها قبل هذا الإصدار. هذه الشجرة مخصصة للبحث والكشف والتحليل التاريخي.
عثرت على حزمة FortiGate SSL-VPN خاصة في البرية. أول إصدار كان دليلاً من العملاء العاملين: أسماء مثل exp/exp_60E-v6.4.7.py و . كل ملف هو . ثغرتان عامتان من نوع n-day، أعيدت صياغتهما عبر العتاد والبرامج الثابتة حتى بدا المجلد ككتالوج قطع غيار.
الكنز هو مصفوفة الإزاحات (offset matrix)، وليس ثغرة جديدة. هذه الحجة موجودة في المرحلة 0 من السلسلة. المرحلة 1 تغطي البدائيتين كسلوك. المرحلة 2 هي خريطة SKU / train / CPU القابلة للبحث. المرحلة 3 هي الصيد.
هذا المستودع هو بقية نفس الحزمة، وليس عائلة استغلال ثانية.
exp/ هي العملاء الخاصون بكل صورة تم وصفهم بالفعل في السلسلة.shellcode/ هي المُطلِق (launcher)، وجالب الحمولة، ومستمعات سرقة الإعدادات التي كُتب هؤلاء العملاء لاستدعائها.exp_*.py لم تحتوِ أبداً على الحمولة. كانت تعرف فقط (1) سحب بايتات خام من "خادم شيلكود" أو (2) GET /s.js وتنفيذها عبر eval. تلك القطع المفقودة موجودة هنا.البدائيتان:
| العائلة | CVE | استشارة Fortinet | اللون العام |
|---|---|---|---|
| A | CVE-2024-21762 | FG-IR-24-015 | Assetnote — Two Bytes is Plenty |
| B | CVE-2023-27997 | FG-IR-23-097 | Lexfo — XORtigate, Bishop Fox |
كلاهما موجود في كتالوج الثغرات المستغلة المعروفة لدى CISA. poc.py لا ينفذ أي من ثغرتي CVE. إنه يختار ويلف العائلتين المصنفتين بالفعل (الكتابة المجزأة 21762؛ تجاوز سعة الكومة enc= 27997).
.
├── poc.py # مُطلِق pocsuite3 / بصمة / مدير عمليات
├── s.js # المرحلة الثانية Node (سارق الإعدادات)
├── send_cmd.py # معالج الاستدعاء لمسار stager
├── init.sh # تثبيت حزم محطة عمل المشغّل
├── requirements.txt # pwntools
├── exp/
│ └── exp_<SKU>-v<FortiOS>.py
└── shellcode/
├── shellcode_server.py # مضخة كتل مسبوقة الطول
├── shellcode_arm # ~2.0 MB مرحلة ثانية خام
└── shellcode_amd64 # ~2.7 MB مرحلة ثانية خام
exp/index.html و shellcode/index.html هما قوائم أدلة عادية من خادم Python http.server. تُظهران فقط أن هذه الشجرة كانت مستضافة كجذر ويب في وقت ما.
هذه النسخة من exp/ هي الكتالوج الأقدم بالإضافة إلى أربعة عملاء إضافيين: exp_30E-v6.2.4.py، exp_30E-v6.2.12.py، exp_30E-v6.2.14.py، exp_40F-v7.0.5.py.
poc.py المنسّق (pocsuite3)
│
├─ بصمة البوابة ───────────── VERSION_LIBS (hash → SKU + FortiOS)
├─ اختيار الملف ───────────── exp/exp_<SKU>-v<ver>.py
│
├─ إذا كان العميل من نوع "stager" (عائلة A ARM / بعض amd64)
│ تشغيل shellcode/shellcode_server.py
│ يقرأ shellcode/shellcode_arm أو shellcode_amd64
│ تشغيل send_cmd.py (انتظار الاستدعاء)
│ تشغيل مستقبل الإعدادات على :9999
│ تشغيل exp_*.py المختار
│
└─ إذا كان العميل من نوع "Node /s.js" (معظم عائلة B + كثير من عائلة A)
تقديم s.js عبر HTTP
تشغيل مستقبل الإعدادات على :9999
تشغيل exp_*.py المختار
→ جدار الحماية GET /s.js → eval → تسريب
خط الأنابيب في سطر واحد: تحديد → اختيار ملف الإزاحة → إفساد sslvpnd → سحب الحمولة → تسريب /data/config/*.gz → أرشفة في جانب المشغّل.
تلك الخطوة الأخيرة هي الهدف. الإصابة هي تنفيذ كود غير مصادق عليه في sslvpnd على جدار الحماية نفسه — مُنهي TLS، وسياسة التوجيه، وجلسات VPN، وغالباً روابط LDAP/RADIUS. لا يوفر FortiOS /bin/sh مفيداً. البحث العام وهذه الحزمة يمران عبر مساعد أوامر داخلي و/أو /bin/node، الذي يشحنه FortiOS فعلاً. تعامل مع الإصابة المؤكدة على أنها اختراق لحافة الشبكة، وليس تعطل خدمة. انظر What a hit means.
poc.py — المُطلِقواجهة المشغّل الأمامية (pocsuite3 POCBase). لا ينفذ CVE-2024-21762 أو CVE-2023-27997.
https://<target>/remote/login?lang=en (الاحتياط GB2312)./sslvpn/js/login.js?q=<md5>.VERSION_LIBS (182 صف hash,SKU,version). هذا الجدول هو سبب قدرة الحزمة على الاختيار بين أكثر من 50 جهازاً دون أن يسمي المشغّل الطراز. نفس طرازات المصفوفة، مدفوعة بتجزئة مورد SSL-VPN عام بدلاً من SNMP أو واجهة إدارة.exp/exp_<SKU>-v<version>.py.s.js → النوع 2 (مُحمّل Node)Shellcode Server → النوع 1 (stager)؛ ثم يبحث عن arm مقابل amd64 في السكربتexp_*.py عبر Popen مع وسائط المضيف/المنفذ/الاستدعاء.عنوان المشغّل الافتراضي في هذه النسخة: HOST_IP من البيئة، وإلا ATTACKER_HOST. تم استبدال عناوين IPv4 الحرفية في هذه الشجرة بتسميات أدوار (المنافذ دون تغيير):
| التسمية | الدور | أين ظهرت |
|---|---|---|
TARGET_HOST | FortiGate قيد الهجوم | لم تُرمَّز أبداً؛ rhost / target من argv (انظر poc.py) |
ATTACKER_HOST | محطة عمل المشغّل | الافتراضي HOST_IP في poc.py؛ عناوين الربط في poc.py، send_cmd.py، shellcode/shellcode_server.py؛ عناصر نائبة s.js / TFTP في exp_*.py تُملأ بـ lhost |
C2_HOST | استدعاء مدمج في هذه النسخة من الحمولة | s.js — ليس lhost المُمرَّر إلى الاستغلال |
| المنفذ | الدور |
|---|---|
| 7777 | الاستدعاء / send_cmd.py |
| 8888 | خادم الشيلكود |
| 9999 | مستقبل الإعدادات (يطابق s.js و send_cmd.py في التسريب) |
إذا كانت تجزئة البوابة مفقودة من VERSION_LIBS، يتوقف برسالة "unknown target hash." إذا طابقت التجزئة لكن ملف exp/ غائب، "no exp."
s.js — المرحلة الثانية Node المفقودةهذا هو الملف الذي تجلبه عملاء عائلة B / عائلة A من نوع Node بعد execute_cmd. إنه ليس شل عكسي عام.
C2_HOST:9999 (مضيف C2، ليس TARGET_HOST وليس lhost / ATTACKER_HOST المُمرَّر إلى الاستغلال — هذه النسخة خُبزت لاستدعاء مشغّل واحد)./data/config/ على جدار الحماية.*.gz غير الرمزية (كائنات إعدادات FortiOS المضغوطة).هذا سارق إعدادات. يفسر لماذا يستمع poc.py أيضاً على 9999 ويعيد تجميع الملفات في نتيجة base64. ابحث عن C2_HOST على المنفذ 9999 من أي مخرج FortiGate. ملاحظات الصيد: المرحلة 3.
send_cmd.py — معالج الاستدعاء لمسار stagerيُستخدم عندما يكون exp_*.py المختار من نوع شيلكود ARM/amd64 (الاستخدام يتضمن خادم شيلكود).
cd /data/config و cat لكل *.gz إلى nc <LHOST> 9999.s.js (سرقة الإعدادات)، نقل مختلف (استدعاء شل مقابل Node).نسخة معلّقة كتعليق استخدمت تأطير base64 بدلاً من cat الخام.
shellcode/shellcode_server.py — مضخة البايتات لـ stagers عائلة Aيطابق البروتوكول الظاهر بالفعل في أكواد ARM32 exp_*.py:
poc.py يستخدم 8888).shellcode_<arch> من نفس الدليل.تتصل stagers exp_*.py هنا، وتُخطط ذاكرة قابلة للكتابة والتنفيذ، وتسحب الكتلة، ثم تعيد الاتصال بـ lhost:lport (7777 → send_cmd.py).
كتل المرحلة الثانية الخام (~2.0 MB ARM، ~2.7 MB amd64). هي ما ينزله الـ stager. ليست كود Thumb الصغير داخل ملفات Python؛ تلك الأكواد تجلب هذه الملفات فقط. تعامل معها كحمولة لمسار غير Node. الحجم يوحي بحمولات مضغوطة أو ثابتة، وليس بضع عشرات من التعليمات.
init.sh — إعداد محطة عمل المشغّللا يُستخدم ضد جدار الحماية. يثبت build-essential، binutils-arm-linux-gnueabihf، و gcc-aarch64-linux-gnu. ذلك لـبناء قطع ARM/AArch64 على صندوق هجوم شبيه بدبيان. متسق مع مؤلف يجمّع stagers بدلاً من شحن Python فقط.
سطر واحد: pwntools. ملفات exp_*.py و shellcode_server.py تستورده. poc.py يريد أيضاً pocsuite3، python-dotenv، mmh3، و requests.
exp/| موصوف بالفعل في السلسلة | الدور في هذه الشجرة |
|---|---|
عائلة A ARM exp_*.py (وسائط stager) | المرحلة الأولى. يستدعي shellcode_server.py + shellcode_arm (أو amd64)، ثم lhost:7777. |
عائلة A/B Node exp_*.py (/s.js) | المرحلة الأولى. HTTP GET للأصل s.js، ثم eval. |
متغيرات 6.0 سلسلة D TFTP / /tmp/s | نفس هدف s.js عبر TFTP؛ ما زالت تتوقع هذا الملف على جذر HTTP للمشغّل. |
لا شيء في الدليل الأصلي ينفذ ثغرة CVE ثالثة. الأعداد، وخريطة حرارة SKU، ومحاذاة train (عائلة A حتى 7.4.0 / 7.4.1؛ عائلة B داخل نافذة 27997) موجودة في المرحلة 0 و المرحلة 2. أثقل إعادة استهداف في الكتالوج الأصلي: FortiGate-60E، 100E، 60F، 100F — عتاد المكاتب الفرعية.
أول إصدار توقف عند "احصل على استدعاء." أجسام المرحلة الثانية كانت مفقودة. هذه الشجرة تجعل الهدف صريحاً:
/data/config/*.gz، وليس "RCE عام." ذلك اختراق للاعتمادات والطوبولوجيا (مستخدمو VPN، والمسارات، والأسرار المخزنة في تلك الكائنات).VERSION_LIBS في poc.py قائمة جاهزة "أي طراز ظنوا أن هذه التجزئة له."استطلاع البوابة وURIs المرحلة الأولى موثقة في Hunting the kit. المميزة منها المذكورة بالفعل في الكتابات العامة وفي هذه الشجرة:
GET /remote/login و /sslvpn/js/login.js?q=/aaaa/bbbb، /remote/error، /remote/info، /remote/hostcheck_validate مع enc=GET /s.js من جدار الحمايةC2_HOST:9999 داخل هذه النسخة من s.js (مضيف C2)ATTACKER_HOST 7777 / 8888 / 9999 (مضيف المهاجم)TARGET_HOST هو rhost المُقدَّم وقت التشغيلاصطد المخرج من جدار الحماية (TARGET_HOST) إلى C2_HOST:9999 وإلى أي ATTACKER_HOST قدّم /s.js خلال النافذة ذات الصلة.
من المقدمة:
PoC عام ضد VM قطعة أثرية مختلفة. هذه الحزمة لمن أجاب على الاستطلاع.
إذا كنت تشغّل FortiGates: جرد الطراز، وFortiOS الدقيق، وSSL-VPN مفعّل أو معطّل، وما إذا كانت البوابة قابلة للوصول من شبكات غير موثوقة. ثم اقرأ المرحلة 2. لا تجرد صناديق سلسلة 60 الفرعية فقط لأن تلك الأسماء كانت الأعلى صوتاً.
استُردت هذه الملفات من البرية أثناء بحث أمني مستقل. لم أنشئها. صدرت كما وُجدت، بعد أن كانت ثغرات CVE ذات الصلة معلنة علناً ومصححة.
للاستخدام البحثي / التعليمي فقط. لا تشغّل أو تنشر أو تستخدم هذه المواد ضد أي مضيف إلا إذا كان لديك إذن كتابي صريح من كل من الطرف المستضيف لهذا المستودع ومالك الأنظمة المستهدفة.