tom@home.htb:~$

Blog o HTB

17 November 2020

Lokálně dostupné služby po footholdu: localhost není boundary

Úvod a kontext

Mnoho systémů se spoléhá na jednoduchou domněnku: tahle služba je bezpečná, protože poslouchá jen na 127.0.0.1. To může fungovat proti anonymnímu návštěvníkovi z internetu. Jakmile ale útočník získá první shell, situace se zásadně mění. Z localhostu se stává plnohodnotná útočná plocha a interní porty najednou představují další vrstvu systému, kterou je potřeba prozkoumat stejně disciplinovaně jako veřejný web.

Tohle téma se částečně dotýká i SSRF, ale není to totéž. Samostatný článek o SSRF, reverse proxy a localhost trust assumptions řeší, jak se na interní službu dostat ještě před footholdem. Tento text naopak řeší situaci po prvním shellu: co hledat na 127.0.0.1, proč to bývá důležité a jak z lokálních služeb nevytvářet tichou druhou administrativu.

Proč localhost po footholdu přestává chránit

127.0.0.1 není autorizační model. Je to jen síťové umístění. Jakmile je útočník uvnitř hostu nebo kontejneru, otevírá se mu přístup k věcem, které byly dosud schované za lokálním bindem:

To je důvod, proč se po footholdu nevyplatí bezhlavě skenovat celou síť, ale velmi cíleně číst, co běží lokálně a jaký bezpečnostní význam tyto služby mají.

Co typicky na localhostu běží

Lokální služby po footholdu mívají několik opakujících se podob.

1. Interní administrační API

Aplikace často skrývá citlivější endpointy za lokální bind:

Předpoklad bývá jednoduchý: na localhost se přece veřejný uživatel nedostane. Po shellu je tento předpoklad pryč.

2. Datové služby a cache

Redis, InfluxDB, databáze, message brokery nebo jiné pomocné služby často neběží veřejně, ale lokálně. To je rozumné pouze tehdy, pokud se zároveň počítá s tím, že první kompromitace hostu tyto služby okamžitě zpřístupní.

3. Pomocné interní workflow

Na localhostu neběží jen standardní produkty. Často tam bývá i:

Právě tyto méně nápadné služby bývají po footholdu nejzajímavější, protože jsou navržené s implicitní důvěrou k lokálnímu volajícímu.

Jak tenhle vzorec vypadal v konkrétních případech

Na ServMonu byl po prvním SSH přístupu klíčový až NSClient++ na 127.0.0.1:8443. Zvenku sice působil jako interní admin rozhraní, ale po port forwardu a přečtení hesla z nsclient.ini se změnil v normálně dosažitelnou službu, která uměla nahrát a spustit vlastní skript. Veřejný web a FTP tedy otevřely jen foothold; skutečný privesc ležel až na localhostu.

Na Devzatu se po vstupu pod účtem patrick ukázala interní InfluxDB na 127.0.0.1:8086, z níž šlo vytáhnout hesla dalších uživatelů. Až další lokální služba na 8443 otevřela přístup k chatu a jeho funkci /file, která vydala rootův klíč. Tady je velmi dobře vidět, že lokální služby po footholdu tvořily celý druhý útokový řetězec.

Na Luanne zase webové RCE samo o sobě nestačilo. Rozhodující byla až localhost-only služba na 127.0.0.1:3001, která po cracknutí .htpasswd vydala soukromý klíč r.michaels a otevřela stabilní SSH foothold.

Na OpenAdminu se stejný pattern projevil na internal.openadmin.htb svázaném s 127.0.0.1:52846. Veřejná RCE v ONA otevřela jen první shell; skutečný posun přinesl až interní vhost, který po port forwardu vydal klíč joanna.

Na Horizontallu zase první shell vedl jen do Strapi účtu strapi, ale teprve 127.0.0.1:8000 odkryl interní Laravel s vlastním RCE. Bez lokální enumerace a SSH port-forwardu by root část vůbec nepřišla na řadu.

Na Oouchu se localhost a interní síť proměnily v druhou polovinu celého řetězce. Po SSH jako qtc už nebyl hlavním tématem veřejný consumer, ale interní kontejnery, uwsgi socket a D-Bus workflow dosažitelné až po prvním shellu.

Na Rope stál další případ na tom, že uživatelský shell dovolil přes SSH port-forward osahat lokální službu na 13907. Nebyla veřejná a sama působila jako interní pomocník. Teprve ruční práce s protokolem a následné zhroucení privilegovaného wrapperu do debuggeru z ní udělaly cestu k rootu.

Na Haystacku zase běžela Kibana konzole jen na 127.0.0.1:5601. Zvenku se k ní nešlo dostat, ale po shellu se ukázalo, že umí načíst lokální soubor a že vedle ní běží log processing workflow s vysokými právy. Opět tedy nešlo o “jednu lokální službu”, ale o celý lokální ekosystém, který po footholdu najednou ztratil ochranu.

I Ready ukazuje stejný vzorec v kompromitovaném kontejneru. Jakmile útočník získal shell uvnitř GitLab kontejneru, lokální Redis už nebyl interní služba chráněná bindem na loopback. Stal se přirozenou součástí útočné plochy daného runtime prostředí.

Jak k localhostu po footholdu přistupovat

Po prvním shellu má smysl uvažovat o localhostu jako o nové mapě systému, ne jako o jednom triku.

1. Nejdřív zjistit, co poslouchá

Bez přehledu o lokálních portech není možné odhadnout další směr. Důležitější než agresivní scan bývají:

ss -lntp
netstat -ano
lsof -i -P -n

Cílem není “najít všechno”. Cílem je pochopit:

2. Číst konfigurace a pomocné soubory

Lokální port sám o sobě ještě neřekne, co služba dělá. Hodnotu často přinese až:

Právě tam se ukáže, zda je lokální služba jen cache, nebo třeba plnohodnotné administrační API.

3. Testovat lokální služby v jejich kontextu

Jakmile je jasné, co na localhostu běží, dává smysl zkoumat:

Pořád nejde o bezhlavé fuzzování. Jde o čtení architektury hostu po kompromitaci. Prakticky se v téhle fázi nejčastěji střídá wget a curl pro ruční HTTP ověřování, Chisel nebo Socat pro vyvedení portu ven a Proxychains, když je potřeba přes vzniklý most obsluhovat další klientské nástroje.

Co se na localhostu hledá nejčastěji

Prakticky se vyplatí cíleně myslet na tyto kategorie:

Společný vzorec je pořád stejný: služba nebyla navržená tak, aby odolávala nedůvěryhodnému uživateli na stejném hostu.

Obrana a bezpečnější návrh

1. Localhost nebrat jako jedinou ochranu

Interní služba má mít vlastní autentizaci a vlastní autorizaci. Bind na 127.0.0.1 může být doplňkové omezení, ne jediný důvod, proč je něco “bezpečné”.

2. Oddělit role a práva procesů

Jestli veřejná aplikace běží pod účtem, který po compromise automaticky vidí citlivé lokální služby, je hranice mezi webem a interní vrstvou příliš tenká.

3. Minimalizovat hodnotu lokálních služeb

Lokální endpoint nemá vracet tajemství, číst libovolné soubory ani spouštět privilegované akce jen proto, že ho volá něco “ze stejného stroje”.

4. Po compromise počítat s plným přístupem k loopbacku

Threat model hostu musí předpokládat, že první shell automaticky znamená přístup k 127.0.0.1. Pokud některá interní služba tento scénář nepřežije, je třeba ji přepracovat nebo izolovat.

5. Monitorovat neobvyklé lokální vztahy mezi službami

Lokální přístupy mezi procesy, které se v běžném provozu nepotkávají, bývají silný signál útoku i chybného návrhu. Totéž platí pro podezřelé port-forwardy a náhlé volání interních konzolí z nečekaného účtu.

Shrnutí klíčových poznatků

Co si odnést do praxe

Další související články

Techniky

Nástroje

tags: localhost - post-exploitation - pivot - services