
Defensives Sicherheitsdemo: seL4-Mikrokernel-Gateway schützt anfällige ICS vor CVE-2019-14462
Ein defensives Sicherheitsforschungsprojekt, das Protocol-Break- und Packet-Forwarding-Architekturen zum Schutz industrieller Steuerungssysteme vor Cyberangriffen vergleicht.
Dokumentation:
- Netzwerkarchitektur – Netzwerkdiagramme und Datenverkehrsfluss
- Container-Architektur – Beziehungen der Docker-Container
- CVE-Erklärungen – Details zu Schwachstellen und Angriffsmechanismen
Moderne ICS/SCADA-Systeme sind Ziel anspruchsvoller Angriffe wie FrostyGoop, der im Januar 2024 über Modbus-TCP auf ukrainische Fernwärmesysteme abzielte und mehr als 600 Haushalte bei Minusgraden ohne Heizung zurückließ. Herkömmliche Sicherheitslösungen (Firewalls, IDS) verwenden Packet-Forwarding-Architekturen, die den Datenverkehr inline überwachen, aber eine einzige TCP-Verbindung durchgängig aufrechterhalten.
Dieses Projekt demonstriert eine Alternative: ein Protocol-Break-Gateway auf Basis des formal verifizierten seL4-Mikrokernels. Durch die Beendigung von TCP-Verbindungen und die Validierung von Protokollsemanitiken vor dem Aufbau neuer Verbindungen zu geschützten Geräten bietet diese Architektur stärkere Sicherheitsgarantien.
┌─────────────────────────────────────────────────────────────────────────────┐
│ 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) │ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
# Lege dein seL4-Kernel-Image ab unter:
gateway/sel4-image/capdl-loader-image-arm-qemu-arm-virt
# Alle Container bauen
sudo docker compose build
# Einzelne Container starten
sudo docker compose up plc # Nur PLC
sudo docker compose up gateway # seL4-Gateway + PLC
sudo docker compose up snort # Snort IDS + PLC
# Alle starten
sudo docker compose up
# Über seL4-Gateway (geschützt - Protocol-Break)
echo -ne '\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01' | nc localhost 502 | xxd
# Über Snort IDS (geschützt - Packet-Forwarding)
echo -ne '\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01' | nc localhost 503 | xxd
# Direkt zum PLC (ungeschützt - anfällig)
echo -ne '\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01' | nc localhost 5020 | xxd
Hinweis: Der Standard-PLC läuft jetzt im CVE-2022-0367-Modus mit ASAN. Verwende
--profile cve14462für CVE-2019-14462-Tests.
Der PLC verwendet die absichtlich anfällige libmodbus 3.1.2. Der Angriff nutzt vertrauenswürdige MBAP-Längenfelder aus:
# PLC im CVE-2019-14462-Modus starten
sudo docker compose --profile cve14462 up plc-14462
# Angriffswerkzeuge bauen
cd cve_tools && make
# Ungeschützten PLC angreifen (Absturz)
./cve_14462_attack 127.0.0.1 5022
# Über seL4 angreifen (BLOCKED)
./cve_14462_attack 127.0.0.1 502
# Über Snort angreifen (DETECTED durch Quickdraw-Regeln)
./cve_14462_attack 127.0.0.1 503
Ein Grenzprüfungsfehler in modbus_mapping_new_start_address() ermöglicht einen Heap-Underflow über Funktionscode 0x17 (Write and Read Registers):
# Standard-PLC läuft im CVE-2022-0367-Modus mit ASAN
sudo docker compose up plc
# Angriffswerkzeuge bauen
cd cve_tools && make
# PLC angreifen – ASAN erkennt Heap-Buffer-Overflow
./cve_0367_attack 127.0.0.1 5020
# Mit benutzerdefinierten Parametern angreifen
./cve_0367_attack 127.0.0.1 5020 88 0x4141 # Beschädigt tab_registers-Zeiger
./cve_0367_attack 127.0.0.1 5020 72 0xFFFF # Beschädigt nb_registers
# Über seL4 angreifen (BLOCKED – Adressvalidierung)
./cve_0367_attack 127.0.0.1 502
# Über Snort angreifen (DETECTED durch benutzerdefinierte Regeln)
./cve_0367_attack 127.0.0.1 503
Technische Details:
start_registers=100, gültige Adressen sind 100–109write_address < 100, was einen negativen Array-Index verursachtmb_mapping-Struktur inklusive Zeiger beschädigenSnort 2.9.18 hat einen Integer-Overflow in seinem Modbus-Preprozessor, der eine Endlosschleife verursacht und jeglichen Datenverkehr durch das IDS vollständig blockiert:
# 1. Überprüfen, ob Snort funktioniert (sollte Modbus-Antwort zurückgeben)
echo -ne '\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01' | nc -w 2 localhost 503 | xxd
# 2. Snort-IDS angreifen
./cve_20685_attack 127.0.0.1 503
# 3. Überprüfen, ob Snort eingefroren ist (sollte ohne Antwort auslaufen)
echo -ne '\x00\x01\x00\x00\x00\x06\x01\x03\x00\x00\x00\x01' | nc -w 5 localhost 503 | xxd
# 4. Snort-CPU überprüfen (sollte 100% sein)
sudo docker exec ics-snort top -b -n 1 | grep snort
# 5. seL4 ist IMMUNE (kein Modbus-Preprozessor, den man ausnutzen könnte)
./cve_20685_attack 127.0.0.1 502 # Keine Auswirkung auf seL4
# 6. Snort nach der Demo neu starten
sudo docker compose restart snort
Warum dies verheerend ist: Snort verwendet den NFQUEUE-Inline-Modus, was bedeutet, dass Pakete in der Kernel-Warteschlange gehalten werden, bis Snort ein Urteil fällt. Wenn Snort hängt, werden keine Urteile zurückgegeben, und der GESAMTE Datenverkehr stoppt – nicht nur IDS-Blindheit, sondern vollständiger Denial-of-Service.
Ein Use-After-Free in Linux netfilter nf_tables (Kernel v5.14–v6.6) ermöglicht einen Container-Ausbruch:
# Prüfen, ob der Host anfällig ist
uname -r # Anfällig: v5.14 – v6.6 (vor Patches)
# Der Exploit ist verfügbar unter:
ls cve_tools/cve-2024-1086/
Warum dies wichtig ist: Docker-Container teilen sich den Host-Kernel. Wenn ein Angreifer Snort kompromittiert (z. B. über CVE-2022-20685), könnte er CVE-2024-1086 nutzen, um aus dem Container auszubrechen und Root-Zugriff auf den Host zu erlangen. seL4 ist immun, da es einen minimalen Mikrokernel und nicht Linux ausführt.
# Vollständige Demo mit 4 Quadranten (PLC, seL4, Snort, Benutzerterminal)
./scripts/demo.sh
# Nur-Snort-Demo mit 3 Fenstern (PLC, Snort, Benutzerterminal)
./scripts/demo-snort.sh
# Automatisierten Vergleich ausführen
./scripts/run_comparison.sh
Mehrere Snort-Konfigurationen sind für Benchmarking der Erkennungseffizienz verfügbar:
# Snort mit bestimmtem Profil ausführen
sudo docker compose --profile snort-talos up
# Erkennungseffizienz vergleichen
sudo docker compose --profile snort-quickdraw up -d
./cve_tools/cve_0367_attack 127.0.0.1 503 # Erkennung testen
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 # Erkennung testen
sudo docker compose --profile snort-combined down
Client ────TCP────► Snort ────TCP────► PLC
(gleiche Verbindung fließt durch)
Client ────TCP1────► seL4 ────TCP2────► PLC
(beendet, validiert, neue Verbindung)
Der PLC simuliert eine Fernwärmesteuerung mit Multi-Master-Unterstützung (Thread-pro-Client-Architektur, typisch für moderne PLCs).
| Modus | Dienst | Port | Beschreibung |
|---|---|---|---|
| CVE-2022-0367 | plc (Standard) |
# Standardmodus (CVE-2022-0367 mit ASAN)
sudo docker compose up plc
# CVE-2019-14462-Modus
sudo docker compose --profile cve14462 up plc-14462
Im CVE-2022-0367-Modus befinden sich die Register an den Adressen 100–109 (in SCADA-Tools Adresse 40101 verwenden):
Dieses Projekt enthält absichtlich anfälligen Code für defensive Sicherheitsforschung. Die anfällige libmodbus 3.1.2 und Snort 2.9.18 sind enthalten, um Sicherheitskonzepte zu demonstrieren.
Setze ungeschützte Komponenten nicht in Produktionsumgebungen ein.
Nur für autorisierte defensive Sicherheitsforschung und Bildungszwecke.
| Aspekt | Protocol-Break (seL4) | Packet-Forwarding (Snort) |
|---|
| CVE-2019-14462 | BLOCKED (Längenvalidierung) | DETECTED (Quickdraw-Regeln) |
| CVE-2022-0367 | BLOCKED (Adressvalidierung) | DETECTED (benutzerdefinierte Regeln) |
| CVE-2022-20685 | IMMUNE (kein Preprozessor) | VULNERABLE (IDS DoS) |
| CVE-2024-1086 | IMMUNE (kein Linux-Kernel) | VULNERABLE (teilt Host-Kernel) |
| Unbekannte Varianten | BLOCKED (strukturelle Validierung) | MISSED (keine Signatur) |
| TCP-Statusangriffe | BLOCKED (Verbindung beendet) | Möglich |
| Angriffsfläche | ~1.000 LoC (Mikrokernel) | ~500.000 LoC (Linux + Snort) |
| Port | Pfad | Architektur | Schutz |
|---|
| 502 | Client → seL4 → PLC | Protocol-Break | Validiert Modbus-Struktur |
| 503 | Client → Snort → PLC | Packet-Forwarding | Regelbasiertes IDS |
| 5020 | Client → PLC (ASAN) | Direkt | CVE-2022-0367-Modus |
| 5022 | Client → PLC | Direkt | CVE-2019-14462-Modus (Profil: cve14462) |
| Profil | Befehl | Regeln | Beschreibung |
|---|
| default | docker compose up snort | 12 | Quickdraw (Industriestandard) |
| quickdraw | --profile snort-quickdraw | 12 | Nur Digital Bond Quickdraw |
| talos | --profile snort-talos | 40 | Talos-Stil mit modbus_func-Schlüsselwörtern |
| modbus | --profile snort-modbus | 13 | Nur benutzerdefinierte CVE-Erkennungsregeln |
| combined | --profile snort-combined | 65 | Alle Regeln kombiniert |
| CVE | Quickdraw | Talos | Custom Modbus |
|---|
| CVE-2019-14462 (MBAP-Länge) | ✅ | ✅ | ✅ |
| CVE-2022-0367 (Heap-Underflow) | ❌ | ✅ | ✅ |
| CVE-2022-20685 (Snort DoS) | ❌ | ✅ | ✅ |
| Schreiboperationen | ❌ | ✅ | ✅ |
| Aufklärung | ✅ | ✅ | ✅ |
| DoS-Funktionscodes | ✅ | ✅ | ❌ |
| Verzeichnis | Beschreibung |
|---|
gateway/ | seL4-Gateway-Container (QEMU + seL4-Kernel) |
snort/ | Snort 2.9.18 IDS mit mehreren Regelprofilen (anfällig für CVE-2022-20685) |
plc/ | Fernwärmesimulation (anfällige libmodbus 3.1.2, CVE-2022-0367-Modus) |
cve_tools/ | Angriffswerkzeuge für CVE-Demonstrationen |
scripts/ | Dienstprogramm- und Experimentierskripte |
docs/ | Dokumentation mit Mermaid-Diagrammen (Netzwerk, Container, CVEs) |
| Werkzeug | Ziel | Beschreibung |
|---|
cve_14462_attack | libmodbus | Heap-Buffer-Overflow durch MBAP-Längenkonflikt |
cve_0367_attack | libmodbus | Heap-Underflow durch ungültige Schreibadresse (FC 0x17) |
cve_20685_attack | Snort | Endlosschleife im Modbus-Preprozessor (DoS) |
cve-2024-1086/ | Linux-Kernel | Privilegieneskalation über nf_tables (Container-Ausbruch) |
| 5020 |
| ASAN-Build, Register an Adresse 100–109 |
| CVE-2019-14462 | plc-14462 | 5022 | Normaler Build, Register an Adresse 0–9 |
| Adresse | Register | Beschreibung | R/W |
|---|
| 100 | HR[0] | Innentemperatur (°C ÷10) | R |
| 101 | HR[1] | Ventilbefehl (0–100 %) | R/W |
| 102 | HR[2] | Temperatursollwert (°C ÷10) | R/W |
| 103 | HR[3] | Modus (0=Manuell, 1=Auto) | R/W |
| 104 | HR[4] | Außentemperatur (°C ÷10) | R |
| 105–109 | HR[5–9] | Status, Position, Vorlauftemperatur, Laufzeit, Leistung | R |