// HackTheBox
Writeup
CVE-2019-9053 (CMS Made Simple <=2.2.9 unauth SQLi) → staff-group PATH hijack of run-parts
Recon
| Port | Service | Version |
|---|---|---|
| 22 | SSH | OpenSSH 9.2p1 Debian |
| 80 | HTTP | Apache 2.4.25 (Debian); robots.txt → /writeup/ |
Two ports, and the web root gives up the lead itself: robots.txt disallows
/writeup/, so that path is the first place to look. It hosts a CMS Made Simple
install — the generator meta tag and a 2019 copyright date pin down both the software
and roughly its version, which matters because CMS Made Simple has a well-known
unauthenticated SQL-injection bug from that era.
Anti-scan daemon: one wrinkle first — aggressive nmap or directory brute-forcing (a flood of 404s) trips a defence that bans port 80 for ~30s. The way through is slow, single requests rather than parallel scanning. The SQLi itself hits a valid endpoint that returns 200, so it doesn’t trip the ban and works fine.
Foothold — CVE-2019-9053 (CMS Made Simple <=2.2.9 unauth SQLi)
CMS Made Simple 2.2.9 and earlier carry CVE-2019-9053, an unauthenticated
SQL injection in the News module. It’s reachable without logging in via
moduleinterface.php?mact=News,m1_,default,0, injecting through the m1_idlist
parameter. The injection is boolean/time-blind — you can’t read data out of the
response directly, so you infer it one character at a time by asking true/false
questions (... like 0x<hex>25 ...) and, for the blind case, wrapping them in
sleep() and timing the reply.
The public exploit is Python 2; porting it to Python 3 (exploit/cmsms_sqli3.py) lets
it run on a modern box. Grinding the injection extracts a user record from the CMS
database:
- username
jkr - salt
5a599ef579066807 - password hash
62def4866937f08cc13bab43bb14e6f7
CMS Made Simple stores passwords as md5(salt + password), so the crack candidate for
each wordlist entry is md5("5a599ef579066807" + word). Running that against
rockyou.txt recovers the plaintext: raykayjay9.
The password turns out to be reused for the system account, so it works straight over SSH:
$ ssh jkr@10.129.42.53
Privilege Escalation — staff-group PATH hijack of run-parts
As jkr the key detail is group membership: jkr is in the staff group (gid 50).
On Debian, staff is meant for local administration, and here it shows: /usr/local/bin
is drwx-wsr-x root staff, i.e. group-writable by staff. And jkr’s PATH is
/usr/local/bin:/usr/bin:/bin:/usr/games — /usr/local/bin comes first, so a
binary we drop there shadows the real one of the same name everywhere else.
The thing to shadow is run-parts. A periodic automated root SSH login happens on
the box, and the login/MOTD flow invokes run-parts by bare name, resolved through
PATH — which for that root session also searches /usr/local/bin first. So we plant
our own run-parts there that makes a root-owned copy of bash with the SUID bit set:
$ cp /bin/bash /tmp/rootbash; chmod 4755
On the next root login (~1-2 min) the login flow runs our run-parts as root, creating
/tmp/rootbash owned by root with SUID. Launching it with -p (so bash keeps the
elevated effective UID instead of dropping privileges) gives a root shell:
/tmp/rootbash -p → root.