// HackTheBox
Writeup
CVE-2019-9053 (CMS Made Simple <=2.2.9 unauth SQLi) → PATH-Hijacking von run-parts über die staff-Gruppe
Aufklärung
| Port | Dienst | Version |
|---|---|---|
| 22 | SSH | OpenSSH 9.2p1 Debian |
| 80 | HTTP | Apache 2.4.25 (Debian); robots.txt → /writeup/ |
Zwei Ports, und das Web-Root liefert den Ansatz selbst: robots.txt verbietet
/writeup/, also ist dieser Pfad die erste Anlaufstelle. Dort läuft eine
CMS-Made-Simple-Installation — das Generator-Meta-Tag und ein Copyright-Datum von
2019 legen sowohl die Software als auch grob ihre Version fest, was wichtig ist, weil
CMS Made Simple aus dieser Zeit einen bekannten unauthentifizierten
SQL-Injection-Bug hat.
Anti-Scan-Daemon: zunächst ein Haken — aggressives nmap oder Directory-Bruteforcing (eine Flut von 404s) löst eine Abwehr aus, die Port 80 für ~30s sperrt. Der Weg durch sind langsame Einzelanfragen statt paralleler Scans. Die SQLi selbst trifft einen gültigen Endpunkt, der 200 zurückgibt, löst also die Sperre nicht aus und funktioniert problemlos.
Erstzugang — CVE-2019-9053 (CMS Made Simple <=2.2.9 unauth SQLi)
CMS Made Simple 2.2.9 und früher tragen CVE-2019-9053, eine unauthentifizierte
SQL-Injection im News-Modul. Sie ist ohne Login erreichbar über
moduleinterface.php?mact=News,m1_,default,0, injiziert über den Parameter m1_idlist.
Die Injection ist boolean-/time-blind — man kann keine Daten direkt aus der Antwort
auslesen, sondern schließt sie Zeichen für Zeichen, indem man Wahr/Falsch-Fragen stellt
(... like 0x<hex>25 ...) und diese für den blinden Fall in sleep() einpackt und die
Antwort misst.
Der öffentliche Exploit ist Python 2; ihn nach Python 3 zu portieren
(exploit/cmsms_sqli3.py) lässt ihn auf einer modernen Box laufen. Das Durchgrinden der
Injection extrahiert einen Benutzerdatensatz aus der CMS-Datenbank:
- Benutzername
jkr - Salt
5a599ef579066807 - Passwort-Hash
62def4866937f08cc13bab43bb14e6f7
CMS Made Simple speichert Passwörter als md5(salt + password), der Crack-Kandidat für
jeden Wortlisteneintrag ist also md5("5a599ef579066807" + word). Führt man das gegen
rockyou.txt aus, wird der Klartext wiederhergestellt: raykayjay9.
Das Passwort ist für das Systemkonto wiederverwendet, funktioniert also direkt über SSH:
$ ssh jkr@10.129.42.53
Rechteausweitung — PATH-Hijacking von run-parts über die staff-Gruppe
Als jkr ist das entscheidende Detail die Gruppenmitgliedschaft: jkr ist in der
Gruppe staff (gid 50). Unter Debian ist staff für die lokale Administration gedacht,
und hier zeigt sich das: /usr/local/bin ist drwx-wsr-x root staff, also
gruppenbeschreibbar durch staff. Und der PATH von jkr ist
/usr/local/bin:/usr/bin:/bin:/usr/games — /usr/local/bin kommt zuerst, ein dort
abgelegtes Binary überschattet also das echte gleichen Namens überall sonst.
Zu überschatten ist run-parts. Auf der Box findet ein periodischer automatisierter
Root-SSH-Login statt, und der Login-/MOTD-Ablauf ruft run-parts mit blankem Namen
auf, aufgelöst über PATH — der für diese Root-Session ebenfalls /usr/local/bin zuerst
durchsucht. Wir legen also dort unser eigenes run-parts ab, das eine root-eigene Kopie
von bash mit gesetztem SUID-Bit erstellt:
$ cp /bin/bash /tmp/rootbash; chmod 4755
Beim nächsten Root-Login (~1-2 Min.) führt der Login-Ablauf unser run-parts als root
aus und erstellt /tmp/rootbash, root-eigen und mit SUID. Startet man es mit -p (damit
bash die erhöhte effektive UID behält, statt die Rechte abzugeben), erhält man eine
Root-Shell: /tmp/rootbash -p → root.