Verwundbarkeits-Validierung: warum ein Fehlversuch kein Sicherheitsbeweis ist
Bei einem beauftragten Sicherheitstest (Pentest) wird geprüft, ob bekannte Schwachstellen in IT-Systemen tatsächlich ausnutzbar sind — nicht nur theoretisch vorhanden. Der mühsame, fehleranfällige Teil ist, jeden einzelnen Kandidaten von Hand durchzuprobieren. Dabei gilt eine unbequeme Wahrheit: Wenn ein Ausnutzungsversuch scheitert, heißt das nicht, dass das System sicher ist — der Versuch kann aus Gründen scheitern, die mit der Schwachstelle nichts zu tun haben. Ein belastbares Prüfergebnis ist deshalb kein Ja/Nein, sondern ein abgestuftes Urteil mit Beleg. Dieser Beitrag beschreibt ein internes Werkzeug, das diese Abstufung erzwingt.
Kontext
Das Werkzeug — intern EasyMS — steuert das etablierte
Framework Metasploit über dessen RPC-Schnittstelle
(pymetasploit3 → msfrpcd) und arbeitet einen
definierten Prüfauftrag ab: gegeben ein Ziel und eine Liste von Kandidaten
(eine CVE-Kennung oder ein explizit benanntes Modul), führt es pro Kandidat
einen risikoarmen check aus, auf Anforderung einen kontrollierten
Exploit-Versuch, und ordnet das Resultat einer belegbaren Klasse zu. Der Betrieb
ist auf autorisierte Ziele beschränkt: check-only ist die
Voreinstellung, ein Exploit läuft nur mit ausdrücklichem --fire, und
eine Scope-Allowlist weist Hosts außerhalb des Auftrags hart ab.
Der Kern: ein Fehlversuch ist kein Sicherheitsbeweis
Ein Exploit, der keine Session öffnet, belegt nur, dass dieser Versuch scheiterte — nicht, dass die Lücke fehlt. Verantwortlich sind in der Praxis regelmäßig Randbedingungen statt der Abwesenheit der Schwachstelle: ein zum Ziel inkompatibler Payload, eine Firewall auf dem Rückkanal, Timing. Ein binäres Ergebnis kollabiert genau diese Unterscheidung und erzeugt damit falsche Entwarnungen — die teuerste Fehlerklasse in einem Sicherheitstest.
Der Ausweg ist, zwei Signale getrennt zu führen, die üblicherweise vermischt werden:
- den CheckCode des Moduls — Metasploits eigene, risikoarme Einschätzung „verwundbar / nicht verwundbar / unklar", ohne Ausnutzung;
- die tatsächliche Session — der Diff über
sessions.listvor und nach dem Versuch, die verlässliche Wahrheit über „habe ich Zugriff erlangt".
Aus der Kombination beider Signale ergeben sich vier belegbare Verdikt-Klassen
(plus ERROR für operative Fehlschläge wie Modul- oder
Verbindungsprobleme):
- CONFIRMED — es wurde eine interaktive Session geöffnet; der Zugriff selbst ist der Beweis.
- LIKELY — der
checkmeldet verwundbar, eine Session kam aber nicht zustande. Das ist ausdrücklich nicht „sicher", sondern der Kandidat für gezielte manuelle Nacharbeit. - NOT_VULNERABLE — der
checkmeldet belastbar „nicht verwundbar". - INCONCLUSIVE — der
checkkann nicht entscheiden (vom Modul nicht unterstützt oder mehrdeutig).
Der praktische Nutzen liegt in LIKELY: Diese Klasse macht die Kandidaten sichtbar, die ein Ja/Nein-Werkzeug stillschweigend als „sicher" verbucht hätte, und lenkt die knappe manuelle Prüfaufmerksamkeit genau dorthin, wo sie etwas ändert.
Warum Standard-Payloads scheitern — zwei im Labor reproduzierte Beispiele
Der LIKELY-Fall ist kein Randphänomen, sondern folgt aus den
Voreinstellungen. Zwei Fälle, reproduziert gegen ein isoliertes Testlabor:
- UnrealIRCd: das Modul wählt von sich aus keinen Payload — ohne explizite Wahl entsteht schlicht keine Session.
- distcc: als Voreinstellung greift
reverse_bash, das/dev/tcpvoraussetzt; die betagte Bash des Ziels stellt das nicht bereit — der Versuch scheitert an der Shell, nicht an der Lücke.
Die Antwort darauf ist eine kurze, kompatible Payload-Fallback-Liste, die
durchprobiert wird, bis eine echte Session entsteht. Damit wandern Fälle, die
allein an der Payload-Wahl gescheitert wären, von LIKELY nach
CONFIRMED — der Unterschied zwischen „vermutlich" und „belegt".
Nachvollziehbarkeit
Jeder Lauf hinterlässt drei Artefakte: ein run.jsonl als
SHA-256-Hash-Chain (per --verify prüfbar; nachträgliche Änderung,
Löschung oder Umsortierung wird erkennbar — dieselbe Mechanik wie in unserem
Audit-Log-Format,
hier aber als eigenständiges Evidenz-Log), das Konsolen-Transkript als Beweis,
und ein replaybares .rc, mit dem sich jeder Befund reproduzieren
lässt. Ein Prüfergebnis ist damit nicht nur eine Behauptung, sondern eine, die
ein Dritter nachrechnen kann.
Status und Grenzen
Belegbar ist der Stand als Prototyp, verifiziert im Juli 2026 gegen ein isoliertes Metasploitable2-Labor (Docker, eigenes Netz, nie ins LAN veröffentlicht). Über Durchsatz oder Einsatz in realen Mandaten steht hier bewusst nichts — das ließe sich derzeit nicht belegen. Und das Werkzeug ersetzt keine Prüfer-Urteilskraft; es strukturiert die Vorarbeit, macht die Fehlerquellen sichtbar und die Ergebnisse nachvollziehbar. Genau darin liegt der Wert: Ein abgestuftes, belegtes Urteil ist ehrlicher als ein aufgeräumtes Ja/Nein — und lenkt die Prüfzeit dahin, wo sie gebraucht wird.