Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Fortigate-SSL-VPN-Exploit-Kit — El tesoro de FortiGate SSL-VPN. CVE-2024-21762 y CVE-2023-27997. 79 clientes de exploit funcionales. 53 SKUs de hardware. 55 compilaciones de FortiOS. | Kitploit
Herramientas/GitHubGitHub/abraxas/fortigate-ssl-vpn-exploit-kit
Frameworks de ExploitsAnálisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebExfiltración de DatosSeguridad de RedesPruebas de PenetraciónComando y ControlRed Teaming
Desarrollo de Payloads
GitHubabraxas/fortigate-ssl-vpn-exploit-kit

Fortigate-SSL-VPN-Exploit-Kit

El tesoro de FortiGate SSL-VPN. CVE-2024-21762 y CVE-2023-27997. 79 clientes de exploit funcionales. 53 SKUs de hardware. 55 compilaciones de FortiOS.

Ver Repositorio
hace 8h 34mAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Kit de FortiGate SSL-VPN (recuperado en la naturaleza)

Archivo de investigación. Recuperado tal como se encontró. Yo no escribí estos archivos.
Publicado: 1 de septiembre de 2026

Este repositorio es el orquestador, los payloads de segunda etapa y los listeners de operador que se sitúan sobre un catálogo de exploits de FortiGate SSL-VPN por SKU. La historia completa, los recuentos y las notas de caza viven en la serie The SSL-VPN pot of gold en Abraxas Labs.

  • Sitio: abraxaslabs.tech
  • Serie: The SSL-VPN pot of gold
  • GitHub: github.com/abraxas
  • Twitter / X: @abraxas_null

No ejecute este material contra ningún host a menos que tenga permiso explícito por escrito tanto de la parte que aloja este repositorio como del propietario de los sistemas objetivo. Los CVE relacionados eran públicos y parcheados antes de esta publicación. Este árbol es para investigación, detección y análisis histórico.


Qué es esto

Encontré un kit privado de FortiGate SSL-VPN en la naturaleza. La primera entrega era un directorio de clientes funcionales: nombres como y . Cada archivo es un cliente de corrupción de memoria . Dos n-days públicos, reestampados a través de hardware y firmware hasta que la carpeta parecía un catálogo de piezas.

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

El oro está en la matriz de offsets, no en un bug nuevo. Ese argumento está en Fase 0 de la serie. Fase 1 cubre las dos primitivas como comportamiento. Fase 2 es el mapa de SKU / train / CPU buscable. Fase 3 es la caza.

Este repositorio es el resto del mismo kit, no una segunda familia de exploits.

  • Los programas exp/ son los clientes por imagen ya descritos en la serie.
  • Los archivos del directorio padre y de shellcode/ son los lanzadores, la descarga de implantes y los listeners de robo de configuración para los que esos clientes fueron escritos.
  • Los archivos exp_*.py nunca contuvieron el implante. Solo sabían (1) extraer bytes crudos de un "servidor de shellcode" o (2) hacer GET /s.js y eval. Esas piezas faltantes están aquí.

Las primitivas:

FamiliaCVEAviso de FortinetColor público
ACVE-2024-21762FG-IR-24-015Assetnote — Two Bytes is Plenty
BCVE-2023-27997FG-IR-23-097Lexfo — XORtigate, Bishop Fox

Ambos están en el catálogo de vulnerabilidades explotadas conocidas de CISA. poc.py no implementa ninguno de los dos CVE. Selecciona y envuelve las dos familias ya clasificadas (escritura fragmentada 21762; desbordamiento de heap enc= 27997).


Estructura

root@kitploit:~
.
├── poc.py                     # lanzador de pocsuite3 / fingerprint / gestor de procesos
├── s.js                       # segunda etapa de Node (ladrón de configuración)
├── send_cmd.py                # manejador de callback para la ruta del stager
├── init.sh                    # instalación de paquetes del puesto de trabajo del operador
├── requirements.txt           # pwntools
├── exp/
│   └── exp_<SKU>-v<FortiOS>.py
└── shellcode/
    ├── shellcode_server.py    # bomba de blobs con prefijo de longitud
    ├── shellcode_arm          # ~2.0 MB de segunda etapa cruda
    └── shellcode_amd64        # ~2.7 MB de segunda etapa cruda

exp/index.html y shellcode/index.html son listados de directorio ordinarios de http.server de Python. Solo muestran que este árbol fue alojado como raíz web en algún momento.

Esta copia de exp/ es el catálogo anterior más cuatro clientes extra: exp_30E-v6.2.4.py, exp_30E-v6.2.12.py, exp_30E-v6.2.14.py, exp_40F-v7.0.5.py.


Cómo se conectan las piezas

root@kitploit:~
poc.py                          orquestador (pocsuite3)
  │
  ├─ portal de fingerprint ──── VERSION_LIBS (hash → SKU + FortiOS)
  ├─ elegir archivo ─────────── exp/exp_<SKU>-v<ver>.py
  │
  ├─ si el cliente es de tipo "stager" (Familia A ARM / algunos amd64)
  │     iniciar shellcode/shellcode_server.py
  │           lee shellcode/shellcode_arm  o  shellcode_amd64
  │     iniciar send_cmd.py                   (esperar callback)
  │     iniciar receptor de configuración en :9999
  │     ejecutar el exp_*.py elegido
  │
  └─ si el cliente es de tipo "Node /s.js" (la mayoría de Familia B + muchas Familia A)
        servir s.js sobre HTTP
        iniciar receptor de configuración en :9999
        ejecutar el exp_*.py elegido
              → firewall GET /s.js → eval → exfiltración

Pipeline en una línea: identificar → elegir archivo de offsets → corromper sslvpnd → extraer implante → exfiltrar /data/config/*.gz → archivar en el lado del operador.

Ese último paso es el punto. Un acierto es ejecución de código no autenticada en sslvpnd en el propio firewall — terminador TLS, política de enrutamiento, sesiones VPN, a menudo enlaces LDAP/RADIUS. FortiOS no ofrece un /bin/sh útil. La investigación pública y este kit pasan ambos por un ayudante de comandos interno y/o /bin/node, que FortiOS realmente incluye. Trate un acierto confirmado como compromiso del borde de la red, no un demonio bloqueado. Ver Qué significa un acierto.


Archivo por archivo

poc.py — lanzador

Interfaz de operador (pocsuite3 POCBase). No implementa CVE-2024-21762 ni CVE-2023-27997.

  1. Obtiene https://<target>/remote/login?lang=en (fallback GB2312).
  2. Extrae el hash anti-caché de /sslvpn/js/login.js?q=<md5>.
  3. Busca ese hash en una tabla incrustada VERSION_LIBS (182 filas hash,SKU,version). Esa tabla es la razón por la que el kit puede elegir entre 50+ appliances sin que el operador nombre el SKU. Mismos SKUs que la matriz, impulsada por un hash de recurso SSL-VPN público en lugar de SNMP o una API de gestión.
  4. Resuelve exp/exp_<SKU>-v<version>.py.
  5. Clasifica el cliente leyendo su fuente:
    • contiene s.js → tipo 2 (cargador Node)
    • el uso menciona Shellcode Server → tipo 1 (stager); luego busca arm vs amd64 en el script
  6. Inicia los ayudantes correspondientes y hace Popen del exp_*.py con argumentos de host/puerto/callback.

Dirección de operador predeterminada en esta copia: HOST_IP del entorno, si no ATTACKER_HOST. Las direcciones IPv4 literales en este árbol han sido reemplazadas con etiquetas de rol (puertos sin cambios):

EtiquetaRolDónde aparecía
TARGET_HOSTFortiGate bajo ataqueNunca codificado; rhost / target de argv (ver poc.py)
ATTACKER_HOSTPuesto de trabajo del operadorHOST_IP predeterminado en poc.py; direcciones de bind en poc.py, send_cmd.py, shellcode/shellcode_server.py; marcadores de posición s.js / TFTP en exp_*.py que se rellenan con lhost
C2_HOSTCallback horneado en esta copia del implantes.js — no el lhost pasado al exploit
PuertoRol
7777Callback / send_cmd.py
8888Servidor de shellcode
9999Receptor de configuración (coincide con s.js y la exfiltración de send_cmd.py)

Si el hash del portal falta en VERSION_LIBS, se detiene con "unknown target hash". Si el hash coincide pero el archivo exp/ está ausente, "no exp".

s.js — la segunda etapa Node faltante

Este es el archivo que los clientes de Familia B / Node Familia A obtienen después de execute_cmd. No es un reverse shell general.

  • Callback codificado C2_HOST:9999 (host C2, no TARGET_HOST y no el lhost / ATTACKER_HOST pasado al exploit — esta copia fue horneada para un callback de operador).
  • Lee /data/config/ en el firewall.
  • Toma archivos *.gz que no son symlinks (objetos de configuración comprimidos de FortiOS).
  • Los descomprime y envía cada uno sobre un pequeño protocolo TCP con prefijo de longitud, luego un marcador de fin.

Eso es un ladrón de configuración. Explica por qué poc.py también escucha en 9999 y reensambla archivos en un resultado base64. Cace C2_HOST en el puerto 9999 desde cualquier egress de FortiGate. Notas de caza: Fase 3.

send_cmd.py — manejador de callback para la ruta del stager

Usado cuando el exp_*.py elegido es del tipo shellcode ARM/amd64 (el uso incluye un servidor de shellcode).

  • Escucha en 7777.
  • Al conectar, escribe un comando: cd /data/config y cat cada *.gz a nc <LHOST> 9999.
  • Mismo objetivo que s.js (robar configuración), transporte diferente (callback de shell vs Node).

Una variante comentada usaba framing base64 en lugar de cat crudo.

shellcode/shellcode_server.py — bomba de bytes para stagers de Familia A

Coincide con el protocolo ya visible en los stubs ARM32 exp_*.py:

  1. Bind al puerto elegido por el operador (poc.py usa 8888).
  2. Acepta una conexión.
  3. Envía una longitud de 4 bytes little-endian.
  4. Envía el blob shellcode_<arch> del mismo directorio.

Los stagers exp_*.py se conectan aquí, mapean memoria escribible-ejecutable, extraen el blob, luego se conectan de vuelta a lhost:lport (7777 → send_cmd.py).

shellcode/shellcode_arm y shellcode/shellcode_amd64

Blobs crudos de segunda etapa (~2.0 MB ARM, ~2.7 MB amd64). Son lo que descarga el stager. No son el stub Thumb diminuto dentro de los archivos Python; esos stubs solo obtienen estos archivos. Trátelos como el implante para la ruta no-Node. El tamaño sugiere payloads empaquetados o estáticos, no unas pocas docenas de instrucciones.

init.sh — configuración del puesto de trabajo del operador

No se usa contra el firewall. Instala build-essential, binutils-arm-linux-gnueabihf y gcc-aarch64-linux-gnu. Eso es para compilar piezas ARM/AArch64 en una caja de ataque tipo Debian. Consistente con un autor que compila stagers en lugar de solo enviar Python.

requirements.txt

Una sola línea: pwntools. Los archivos exp_*.py y shellcode_server.py lo importan. poc.py también quiere pocsuite3, python-dotenv, mmh3 y requests.


Relación con los clientes exp/

Ya descrito en la serieRol en este árbol
Familia A ARM exp_*.py (argumentos de stager)Primera etapa. Llama a shellcode_server.py + shellcode_arm (o amd64), luego lhost:7777.
Familia A/B Node exp_*.py (/s.js)Primera etapa. HTTP GET del s.js padre, luego eval.
Variantes 6.0 D-series TFTP / /tmp/sMismo objetivo s.js vía TFTP; aún espera este archivo en la raíz HTTP del operador.

Nada en el directorio padre implementa un tercer CVE. Recuentos, mapa de calor de SKU y alineación de trains (Familia A hasta 7.4.0 / 7.4.1; Familia B dentro de la ventana de 27997) están en Fase 0 y Fase 2. Reorientación más pesada en el catálogo original: FortiGate-60E, 100E, 60F, 100F — hardware de oficina sucursal.


Qué cambia esto

La primera entrega se detuvo en "obtener un callback". Los cuerpos de segunda etapa faltaban. Este árbol hace explícito el objetivo:

  1. Robar configuración de FortiOS de /data/config/*.gz, no "RCE genérico". Eso es compromiso de credenciales y topología (usuarios VPN, rutas, secretos almacenados en esos objetos).
  2. El conjunto de IOCs es concreto (ver abajo).
  3. VERSION_LIBS en poc.py es una lista lista para usar de "qué SKU pensaron que era este hash".
  4. El kit es un pipeline completo de robo de configuración, no una bolsa de PoCs inconexos.

Indicadores (esta copia)

El reconocimiento del portal y los URIs de primera etapa están documentados en Hunting the kit. Los distintivos ya señalados en escritos públicos y en este árbol:

  • Reconocimiento del portal: GET /remote/login y /sslvpn/js/login.js?q=
  • URIs de primera etapa: /aaaa/bbbb, /remote/error, /remote/info, /remote/hostcheck_validate con enc=
  • HTTP saliente GET /s.js desde el firewall
  • TCP saliente desde el firewall a 7777 / 8888 / 9999
  • C2 horneado C2_HOST:9999 dentro de esta copia de s.js (host C2)
  • Listeners de operador en puertos ATTACKER_HOST 7777 / 8888 / 9999 (host atacante)
  • El objetivo nunca está codificado: TARGET_HOST es rhost suministrado en tiempo de ejecución

Cace el egress desde el firewall (TARGET_HOST) a C2_HOST:9999 y a cualquier ATTACKER_HOST que sirvió /s.js durante la ventana relevante.


Qué no prueba este kit

De la introducción:

  • Un 0-day nuevo. Las primitivas son n-days con escritos públicos.
  • FortiProxy, FortiManager, FortiAnalyzer, FortiWeb. Sin muestras aquí.
  • SKUs no en la matriz recuperada (muchas unidades 70F / 90G / 120G, imágenes solo-VM, chasis 6K / 7K). Sin offsets compilados.
  • Builds más allá de los cortes publicados por Fortinet. Confirme contra el aviso en vivo (FG-IR-24-015, FG-IR-23-097), no esta carpeta.
  • Persistencia. Eso viviría en un seguimiento que aún no está implementado como una tercera etapa distinta en estos scripts.

Un PoC público contra una VM es un artefacto diferente. Este paquete es para quien respondió al reconocimiento.


Serie

  1. Fase 0 · Introducción — el hallazgo, los recuentos, lo que está en juego.
  2. Fase 1 · Dos puertas públicas — Familia A y Familia B como comportamiento, no una receta.
  3. Fase 2 · La matriz — 53 SKUs, trains, CPU. Buscable.
  4. Fase 3 · Cazando el kit — URIs distintivos, cortes de parches, qué hacer si el portal era alcanzable.

Si ejecuta FortiGates: inventario de modelo, FortiOS exacto, SSL-VPN activado o desactivado, si el portal era alcanzable desde redes no confiables. Luego lea Fase 2. No inventarie solo cajas de sucursal de la serie 60 porque esos nombres de archivo eran los más ruidosos.


Aviso

Estos archivos fueron recuperados en la naturaleza durante investigación de seguridad independiente. Yo no los creé. Se publican tal como se encontraron, después de que los CVE relacionados fueron divulgados públicamente y parcheados.

Solo para investigación / uso educativo. No ejecute, despliegue ni use este material contra ningún host a menos que tenga permiso explícito por escrito tanto de la parte que aloja este repositorio como del propietario de los sistemas objetivo.

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

Descargar herramienta