Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Fortigate-SSL-VPN-Exploit-Kit — Le pot d'or SSL-VPN FortiGate. CVE-2024-21762 et CVE-2023-27997. 79 clients d'exploitation fonctionnels. 53 références matérielles. 55 builds FortiOS. | Kitploit
Outils/GitHubGitHub/abraxas/fortigate-ssl-vpn-exploit-kit
Frameworks d'ExploitationAnalyse des VulnérabilitésExploitationExploitation d'Applications WebExfiltration de DonnéesSécurité RéseauTests d'IntrusionCommandement et ContrôleRed Teaming
Développement de Charges Utiles
GitHubabraxas/fortigate-ssl-vpn-exploit-kit

Fortigate-SSL-VPN-Exploit-Kit

Le pot d'or SSL-VPN FortiGate. CVE-2024-21762 et CVE-2023-27997. 79 clients d'exploitation fonctionnels. 53 références matérielles. 55 builds FortiOS.

Voir le dépôt
il y a 9h 4mPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

Kit FortiGate SSL-VPN (récupéré dans la nature)

Archive de recherche. Récupéré tel quel. Je n'ai pas écrit ces fichiers.
Publié : 1er septembre 2026

Ce dépôt contient l'orchestrateur, les charges utiles de deuxième étape et les écouteurs opérateur qui se superposent à un catalogue d'exploits FortiGate SSL-VPN par SKU. L'histoire complète, les comptages et les notes de chasse se trouvent dans la série The SSL-VPN pot of gold sur Abraxas Labs.

  • Site : abraxaslabs.tech
  • Série : The SSL-VPN pot of gold
  • GitHub : github.com/abraxas
  • Twitter / X : @abraxas_null

N'exécutez pas ce matériel contre un hôte sans autorisation écrite explicite de la partie hébergeant ce dépôt et du propriétaire des systèmes cibles. Les CVE associées étaient publiques et corrigées avant cette publication. Cette arborescence est destinée à la recherche, à la détection et à l'analyse historique.


Ce que c'est

J'ai trouvé un kit privé FortiGate SSL-VPN dans la nature. Le premier dépôt était un répertoire de clients fonctionnels : des noms comme et . Chaque fichier est un client de corruption mémoire . Deux n-days publics, réestampillés sur du matériel et des firmwares jusqu'à ce que le dossier ressemble à un catalogue de pièces détachées.

exp/exp_60E-v6.4.7.py
exp/exp_1000D-v7.4.0.py
par SKU, par FortiOS

L'or est la matrice d'offsets, pas un nouveau bug. Cet argument est développé dans Phase 0 de la série. Phase 1 couvre les deux primitives en tant que comportement. Phase 2 est la carte SKU / train / CPU consultable. Phase 3 est la chasse.

Ce dépôt est le reste du même kit, pas une deuxième famille d'exploits.

  • Les programmes exp/ sont les clients par image déjà décrits dans la série.
  • Les fichiers du répertoire parent et de shellcode/ sont le lanceur, la récupération d'implant et les écouteurs de vol de configuration que ces clients étaient conçus pour appeler.
  • Les fichiers exp_*.py ne contenaient jamais l'implant. Ils savaient seulement (1) récupérer des octets bruts depuis un « serveur de shellcode » ou (2) faire GET /s.js et l'eval. Ces pièces manquantes sont ici.

Les primitives :

FamilleCVEAvis FortinetCouleur publique
ACVE-2024-21762FG-IR-24-015Assetnote — Two Bytes is Plenty
BCVE-2023-27997FG-IR-23-097Lexfo — XORtigate, Bishop Fox

Les deux figurent dans le catalogue des vulnérabilités exploitées connues de la CISA. poc.py n'implémente pas l'une ou l'autre de ces CVE. Il sélectionne et encapsule les deux familles déjà classifiées (écriture par blocs 21762 ; débordement de tas enc= 27997).


Structure

root@kitploit:~
.
├── poc.py                     # lanceur pocsuite3 / empreinte / gestionnaire de processus
├── s.js                       # deuxième étape Node (voleur de configuration)
├── send_cmd.py                # gestionnaire de rappel pour le chemin stager
├── init.sh                    # installation des paquets du poste opérateur
├── requirements.txt           # pwntools
├── exp/
│   └── exp_<SKU>-v<FortiOS>.py
└── shellcode/
    ├── shellcode_server.py    # pompe de blobs préfixés par longueur
    ├── shellcode_arm          # ~2,0 Mo de deuxième étape brute
    └── shellcode_amd64        # ~2,7 Mo de deuxième étape brute

exp/index.html et shellcode/index.html sont des listes de répertoires Python http.server ordinaires. Elles montrent seulement que cette arborescence a été hébergée comme racine web à un moment donné.

Cette copie de exp/ est le catalogue antérieur plus quatre clients supplémentaires : exp_30E-v6.2.4.py, exp_30E-v6.2.12.py, exp_30E-v6.2.14.py, exp_40F-v7.0.5.py.


Comment les pièces s'assemblent

root@kitploit:~
poc.py                          orchestrateur (pocsuite3)
  │
  ├─ portail d'empreinte ────── VERSION_LIBS (hash → SKU + FortiOS)
  ├─ sélection du fichier ───── exp/exp_<SKU>-v<ver>.py
  │
  ├─ si le client est de type "stager" (Famille A ARM / certains amd64)
  │     démarrer shellcode/shellcode_server.py
  │           lit shellcode/shellcode_arm  ou  shellcode_amd64
  │     démarrer send_cmd.py                   (attente du rappel)
  │     démarrer le récepteur de configuration sur :9999
  │     exécuter le exp_*.py choisi
  │
  └─ si le client est de type "Node /s.js" (plupart Famille B + beaucoup Famille A)
        servir s.js via HTTP
        démarrer le récepteur de configuration sur :9999
        exécuter le exp_*.py choisi
              → pare-feu GET /s.js → eval → exfiltration

Pipeline en une ligne : identifier → sélectionner le fichier d'offsets → corrompre sslvpnd → récupérer l'implant → exfiltrer /data/config/*.gz → archiver côté opérateur.

Cette dernière étape est le point crucial. Une réussite est une exécution de code non authentifiée dans sslvpnd sur le pare-feu lui-même — terminateur TLS, politique de routage, sessions VPN, souvent des liaisons LDAP/RADIUS. FortiOS n'offre pas de /bin/sh utile. La recherche publique et ce kit passent tous deux par un assistant de commande interne et/ou /bin/node, que FortiOS fournit effectivement. Considérez une réussite confirmée comme une compromission de la périphérie réseau, pas un démon planté. Voir Ce que signifie une réussite.


Fichier par fichier

poc.py — lanceur

Interface opérateur (pocsuite3 POCBase). Il n'implémente pas CVE-2024-21762 ni CVE-2023-27997.

  1. Récupère https://<cible>/remote/login?lang=en (repli GB2312).
  2. Extrait le hash anti-cache de /sslvpn/js/login.js?q=<md5>.
  3. Recherche ce hash dans une table intégrée VERSION_LIBS (182 lignes hash,SKU,version). Cette table est la raison pour laquelle le kit peut choisir parmi plus de 50 appliances sans que l'opérateur nomme le SKU. Mêmes SKU que la matrice, pilotés par un hash de ressource SSL-VPN public plutôt que par SNMP ou une API de gestion.
  4. Résout exp/exp_<SKU>-v<version>.py.
  5. Classe le client en lisant son code source :
    • contient s.js → type 2 (chargeur Node)
    • l'usage mentionne Shellcode Server → type 1 (stager) ; puis recherche arm vs amd64 dans le script
  6. Démarre les assistants correspondants et lance Popen sur le exp_*.py avec les arguments hôte/port/rappel.

Adresse opérateur par défaut dans cette copie : HOST_IP depuis l'environnement, sinon ATTACKER_HOST. Les adresses IPv4 littérales de cette arborescence ont été remplacées par des étiquettes de rôle (ports inchangés) :

ÉtiquetteRôleOù elle apparaissait
TARGET_HOSTFortiGate attaquéJamais codé en dur ; rhost / target depuis argv (voir poc.py)
ATTACKER_HOSTPoste opérateurHOST_IP par défaut dans poc.py ; adresses de liaison dans poc.py, send_cmd.py, shellcode/shellcode_server.py ; espaces réservés s.js / TFTP des exp_*.py remplis avec lhost
C2_HOSTRappel intégré dans cette copie de l'implants.js — pas le lhost passé à l'exploit
PortRôle
7777Rappel / send_cmd.py
8888Serveur de shellcode
9999Récepteur de configuration (correspond à l'exfiltration de s.js et send_cmd.py)

Si le hash du portail est absent de VERSION_LIBS, il s'arrête avec « unknown target hash ». Si le hash correspond mais que le fichier exp/ est absent, « no exp ».

s.js — la deuxième étape Node manquante

C'est le fichier que les clients Famille B / Node Famille A récupèrent après execute_cmd. Ce n'est pas un reverse shell général.

  • Rappel codé en dur C2_HOST:9999 (hôte C2, pas TARGET_HOST et pas le lhost / ATTACKER_HOST passé à l'exploit — cette copie a été figée pour un seul rappel opérateur).
  • Lit /data/config/ sur le pare-feu.
  • Prend les fichiers *.gz non-symlinks (objets de configuration compressés FortiOS).
  • Les décompresse et les envoie chacun via un petit protocole TCP préfixé par longueur, puis un marqueur de fin.

C'est un voleur de configuration. Cela explique pourquoi poc.py écoute aussi sur 9999 et réassemble les fichiers dans un résultat base64. Cherchez C2_HOST sur le port 9999 depuis toute sortie FortiGate. Notes de chasse : Phase 3.

send_cmd.py — gestionnaire de rappel pour le chemin stager

Utilisé lorsque le exp_*.py choisi est du type shellcode ARM/amd64 (l'usage inclut un serveur de shellcode).

  • Écoute sur 7777.
  • À la connexion, écrit une commande : cd /data/config et cat de chaque *.gz vers nc <LHOST> 9999.
  • Même objectif que s.js (voler la configuration), transport différent (rappel shell vs Node).

Une variante commentée utilisait un encadrement base64 au lieu d'un cat brut.

shellcode/shellcode_server.py — pompe d'octets pour les stagers Famille A

Correspond au protocole déjà visible dans les stubs ARM32 exp_*.py :

  1. Lie le port choisi par l'opérateur (poc.py utilise 8888).
  2. Accepte une connexion.
  3. Envoie une longueur de 4 octets en little-endian.
  4. Envoie le blob shellcode_<arch> depuis le même répertoire.

Les stagers exp_*.py se connectent ici, mappent de la mémoire exécutable-écrivable, récupèrent le blob, puis se reconnectent à lhost:lport (7777 → send_cmd.py).

shellcode/shellcode_arm et shellcode/shellcode_amd64

Blobs bruts de deuxième étape (~2,0 Mo ARM, ~2,7 Mo amd64). C'est ce que le stager télécharge. Ce ne sont pas les petits stubs Thumb dans les fichiers Python ; ces stubs ne font que récupérer ces fichiers. Traitez-les comme l'implant pour le chemin non-Node. La taille suggère des charges utiles compressées ou statiques, pas quelques dizaines d'instructions.

init.sh — configuration du poste opérateur

Non utilisé contre le pare-feu. Installe build-essential, binutils-arm-linux-gnueabihf et gcc-aarch64-linux-gnu. C'est pour compiler des morceaux ARM/AArch64 sur une machine d'attaque de type Debian. Cohérent avec un auteur qui compile des stagers plutôt que de ne livrer que du Python.

requirements.txt

Une seule ligne : pwntools. Les fichiers exp_*.py et shellcode_server.py l'importent. poc.py veut aussi pocsuite3, python-dotenv, mmh3 et requests.


Relation avec les clients exp/

Déjà décrit dans la sérieRôle dans cette arborescence
exp_*.py ARM Famille A (arguments stager)Première étape. Appelle shellcode_server.py + shellcode_arm (ou amd64), puis lhost:7777.
exp_*.py Node Famille A/B (/s.js)Première étape. HTTP GET du s.js parent, puis eval.
Variantes TFTP / /tmp/s série D 6.0Même objectif s.js via TFTP ; attend toujours ce fichier sur la racine HTTP de l'opérateur.

Rien dans le répertoire parent n'implémente une troisième CVE. Les comptages, la carte thermique des SKU et l'alignement des trains (Famille A jusqu'à 7.4.0 / 7.4.1 ; Famille B dans la fenêtre 27997) sont dans Phase 0 et Phase 2. Reciblage le plus lourd dans le catalogue original : FortiGate-60E, 100E, 60F, 100F — matériel de succursale.


Ce que cela change

Le premier dépôt s'arrêtait à « obtenir un rappel ». Les corps de deuxième étape manquaient. Cette arborescence rend l'objectif explicite :

  1. Voler la configuration FortiOS depuis /data/config/*.gz, pas « RCE générique ». C'est une compromission d'identifiants et de topologie (utilisateurs VPN, routes, secrets stockés dans ces objets).
  2. L'ensemble d'IOC est concret (voir ci-dessous).
  3. VERSION_LIBS dans poc.py est une liste prête à l'emploi « quel SKU pensaient-ils que ce hash était ».
  4. Le kit est un pipeline complet de vol de configuration, pas un sac de PoC déconnectés.

Indicateurs (cette copie)

La reconnaissance du portail et les URI de première étape sont documentées dans Hunting the kit. Les plus distinctifs déjà signalés dans les écrits publics et dans cette arborescence :

  • Reconnaissance du portail : GET /remote/login et /sslvpn/js/login.js?q=
  • URI de première étape : /aaaa/bbbb, /remote/error, /remote/info, /remote/hostcheck_validate avec enc=
  • HTTP sortant GET /s.js depuis le pare-feu
  • TCP sortant depuis le pare-feu vers 7777 / 8888 / 9999
  • C2 intégré C2_HOST:9999 dans cette copie de s.js (hôte C2)
  • Écouteurs opérateur sur les ports ATTACKER_HOST 7777 / 8888 / 9999 (hôte attaquant)
  • La cible n'est jamais codée en dur : TARGET_HOST est le rhost fourni au moment de l'exécution

Cherchez la sortie du pare-feu (TARGET_HOST) vers C2_HOST:9999 et vers tout ATTACKER_HOST ayant servi /s.js pendant la fenêtre concernée.


Ce que ce kit ne prouve pas

D'après l'introduction :

  • Un nouveau 0-day. Les primitives sont des n-days avec des écrits publics.
  • FortiProxy, FortiManager, FortiAnalyzer, FortiWeb. Aucun échantillon ici.
  • Les SKU absents de la matrice récupérée (nombreuses unités 70F / 90G / 120G, images VM uniquement, châssis 6K / 7K). Aucun offset compilé.
  • Les builds au-delà des coupes publiées par Fortinet. Confirmez avec l'avis en vigueur (FG-IR-24-015, FG-IR-23-097), pas ce dossier.
  • La persistance. Elle vivrait dans une suite qui n'est toujours pas implémentée comme troisième étape distincte dans ces scripts.

Un PoC public contre une VM est un artefact différent. Ce pack est destiné à celui qui a répondu à la reconnaissance.


Série

  1. Phase 0 · Introduction — la découverte, les comptages, les enjeux.
  2. Phase 1 · Deux portes publiques — Famille A et Famille B comme comportement, pas une recette.
  3. Phase 2 · La matrice — 53 SKU, trains, CPU. Consultable.
  4. Phase 3 · Chasser le kit — URI distinctifs, coupes de correctifs, que faire si le portail était accessible.

Si vous exploitez des FortiGates : inventoriez le modèle, le FortiOS exact, SSL-VPN activé ou non, et si le portail était accessible depuis des réseaux non fiables. Puis lisez Phase 2. N'inventoriez pas seulement les boîtiers de succursale série 60 parce que ces noms de fichiers étaient les plus visibles.


Avis

Ces fichiers ont été récupérés dans la nature lors d'une recherche en sécurité indépendante. Je ne les ai pas créés. Ils sont publiés tels que trouvés, après que les CVE associées ont été divulguées publiquement et corrigées.

Usage recherche / éducatif uniquement. N'exécutez, ne déployez et n'utilisez pas ce matériel contre un hôte sans autorisation écrite explicite de la partie hébergeant ce dépôt et du propriétaire des systèmes cibles.

— @abraxas_null · abraxaslabs.tech · github.com/abraxas

Télécharger l’outil