
Dieses Repository enthält einen Proof-of-Concept-Exploit für CVE-2019-0217 sowie ein Dockerfile zum Einrichten eines Webservers, der anfällig für die CVE ist.
In Apache HTTP Server 2.4 Version 2.4.38 und früher konnte eine Race Condition in mod_auth_digest bei einem Threaded-Server einem Benutzer mit gültigen Anmeldedaten ermöglichen, sich unter einem anderen Benutzernamen zu authentifizieren und so konfigurierte Zugriffskontrollbeschränkungen zu umgehen.
Wenn ein Client versucht, auf eine Ressource hinter HTTP Digest Auth zuzugreifen, antwortet der Server mit einem 401-Statuscode und einem WWW-Authenticate-Header, der in etwa dem folgenden Format entspricht:
Digest realm="rlm", nonce="TToc8M0jBgA=7afa4f292c97632a6c17eec458d3db31021b111f", algorithm=MD5, qop="auth"
Der Client berechnet den HA1, den MD5-Digest von A1 (d. h. Benutzername:Realm:Passwort), und fügt dann Nonce und andere Metadaten wie cnonce hinzu, um A2 zu erhalten, dessen MD5-Digest wiederum HA2 ergibt. Diesen sendet der Client zusammen mit Benutzername, cnonce und anderen Metadaten als Antwort im Authentication-Header:
'Digest username="attacker", realm="rlm", nonce="TToc8M0jBgA=7afa4f292c97632a6c17eec458d3db31021b111f", uri="/scripts/userprofile.cgi", response="bcb433e4071fa228fe0c9452a7495efd", algorithm="MD5", qop="auth", nc=00000001, cnonce="2309510923095109"
^^^^^^^^^^
Wie unten beschrieben, kann der hervorgehobene Teil des obigen Headers manipuliert werden, um die erforderliche Race Condition für den Exploit zu erzeugen.
Die Schwachstelle wurde durch diesen Commit behoben.
Betrachtet man den Code des Moduls mod_auth_digest (insbesondere die Funktion get_hash in mod_auth_digest.c), so zeigt sich, dass der Server zuerst den Authentication-Header parst, um zu bestimmen, was in den Anführungszeichen nach username= steht, und dies als den Benutzer behandelt, der mit der Anfrage verknüpft ist (r->user). Anschließend wird geprüft, ob dieser „Benutzer“ Zugriff auf die angeforderte Ressource hat. Ist dies der Fall, ruft die Funktion get_hash den entsprechenden HA1 aus der Authentifizierungsdatei ab.
Vor dem Commit zur Behebung der Schwachstelle wurde der auf diese Weise abgerufene HA1 in der Variablen conf = (digest_config_rec *) ap_get_module_config(r->per_dir_config,&auth_digest_module) gespeichert, die offenbar nicht threadsicher ist.
Was uns den Exploit liefert:
Basierend auf dem obigen Abschnitt zur Schwachstellenanalyse sollte es möglich sein, eine Race Condition zu erzeugen, indem gleichzeitig Anfragen mit gültigem Authentication-Header und Anfragen mit gefälschtem Authentication-Header gesendet werden (dieser ist derselbe wie der gültige Header, nur dass der Wert von username= auf den Zielbenutzer gesetzt ist, als den sich der Angreifer ausgeben möchte).
In diesem Exploit verwendete Begriffe: - Angreifer: Der Benutzer, der diesen Exploit ausführt. Er verfügt über einen gültigen Benutzernamen und ein gültiges Passwort für sein eigenes Konto. - Opfer: Der Benutzer, als den sich der Angreifer ausgeben möchte. Der Benutzername des Opfers ist bekannt, das Passwort jedoch (offensichtlich) nicht.
Ich konnte diese Methode zum Laufen bringen, indem ich eine Reihe von Python-Threads erzeugte, von denen einige Anfragen des ersten Typs und andere Anfragen des zweiten Typs sendeten, aber es war unzuverlässig und erforderte eine große Anzahl von Anfragen. Das führte mich zur Verwendung des Turbo Intruder von Burp (kostenlos), der die Anfragen zuverlässig parallel sendet. Leider ist die CLI-Unterstützung von Turbo Intruder fehlerhaft, daher müssen einige Teile des Exploits über die GUI ausgeführt werden.
Um den Beispielserver mit der Schwachstelle zu verwenden, den ich in dieses Repository aufgenommen habe, führe Folgendes aus:
$ cd sample_vulnerable_server
$ docker build -t poc_httpd .
$ docker run -p 8038:80 poc_httpd
Führe generate_turbo_intruder_script.py aus, nachdem du die Variablen oben konfiguriert hast:
# Configuration
URL = 'http://localhost:8038/scripts/userprofile.cgi' # location to the resource protected by digest auth
ATTACKER_USERNAME = 'attacker'
ATTACKER_PASSWORD = 'known'
VICTIM_USERNAME = 'victim'
NUMBER_OF_REQUESTS = 2000 # number of concurrent requests sent to catch a glimpse of the race condition
Dieses Skript erzeugt dann zwei Dateien, generated/turbo_intruder_script.py und generated/request.txt, im aktuellen Verzeichnis.
Öffne nun BurpSuite Community Edition und installiere die Erweiterung „Turbo Intruder“, indem du zu Erweiterungen -> BApp Store gehst, falls du das nicht bereits getan hast.
Öffne den Burp Repeater. Lege Host und Port des Ziels fest:

Füge den Inhalt von generated/request.txt in den Request-Bereich ein:

Klicke mit der rechten Maustaste irgendwo in den Request-Bereich und wähle 'Extensions->Turbo Intruder->Send to Turbo Intruder'.

Füge den Inhalt von generated/turbo_intruder_script.py in den Skript-Bereich ein:

Klicke schließlich unten im Turbo-Intruder-Fenster auf die Schaltfläche „Attack“. Es sollten alle erfolgreichen Ergebnisse auf dem resultierenden Bildschirm angezeigt werden:
