Analýza cíleného útoku, část druhá
Máme tu pokračování Analýzy cíleného útoku. Předem se omlouváme za zpoždění s vydáním druhého dílu, vzniklé pracovním vytížením, projekty, novými skutečnostmi korespondujícími s napadením serveru a aplikačním DDoS útokem, který trval asi měsíc po útoku na náš server.
V minulém dílu Analýzy cíleného útoku jsme si podrobně rozebrali co podezřelého máme sledovat v logu webserveru, počáteční analýzu útoku, odhalení postupu útočníků za pomoci logů serveru, jak komunikovat s hostingovou společností a jaká data a informace po nich chtít. Nakonec jsme vystavili většinu útočných skriptů, jež útočníci zanechali na serveru. Vzhledem ke skutečnosti, že od prvního dílu článku už uplynul nejeden měsíc, doporučujeme článek před pokračováním znovu pročíst.
Jak došlo k průniku?
Jak bylo řečeno v prvním dílu, úspěšnému přihlášení na doménu SP předcházelo 3500 přístupů na administrační stránku jedné ze subdomén. Následně se útočníci úspěšně přihlásili a dále infiltrovali další místa portálu.
První teorie
Subdoména běžela na redakčním systému WordPress (WP). Jedná se o velice známý a jednoduchý CMS provozovaný na cca 60-ti milionech webů. Díky své popularitě je bohužel až příliš častým cílem automatizovaných útoků a podrobován důkladné analýze zdrojových kódů. V těch se útočníci snaží najít chybu, aby tak mohli napadnout co možná největší počet instalací. Většina těchto webů je ale napadena hlavně díky modulům třetích stran. Ty si uživatel instaluje, aby rozšířil funkčnost svého webu. Takových modulů jsou desítky tisíc a není v silách vývojářů WP, aby dokázali kontroloval kvalitu kódu. Pokud si tedy uživatel aktivuje modul, na kterém je známá existující zranitelnost, je jen otázkou času, než bude web napaden a uživatel sám ani nic nepozná. Tento web může být následně zneužit pro další útok, export soukromých dat z databáze, sloužit jako dočasné skladiště dat, nebo začleněn do botnetu orientující se na WP.
Po diskuzi s RubberDuckem jsem byl ujistěn, že WP běžel na poslední existující verzi a na webu bylo aktivováno jen asi pět modulů, na než jsme nenašli existující exploity. Navíc logy serveru nenaznačovaly, že by útočníky zajímal některý z existujících modulů. I když se v logu objevilo mnoho dotazů na moduly WP, žádný z modulů se známou zranitelností se na webu nevyskytoval. WP dále obsahoval několik bezpečnostních modulů zabraňujících běžným útokům typu SQLi, XSS, CSRF, RFi/LFi atd. Z toho můžeme usuzovat, že tohle zřejmě nebyl onen úspěšný vektor útoku.
Bezpečné nastavení WP by zasloužilo vlastní článek, a proto v tuto chvíli alespoň odkážeme čtenáře na web vývojářů WP věnující se bezpečnosti.
Druhá teorie
Náš druhý odhad byl jednoduchý a přímočarý: jednalo se o slovníkový útok nebo útok hrubou silou, kterému nakonec subdoména podlehla. Jenže tato teorie hned záhy dostala dosti významnou trhlinu. Na dané subdoméně existuje pouze jediný účet, jehož délka hesla přesahuje 15 znaků. Takové heslo by se sotva ve slovníku mohlo nacházet. Muselo by se jednat buď o hodně speciální slovník nebo by útočník musel mít opravdu velké štěstí už proto, že heslo je netriviálního charakteru. Pokud opomeneme, že heslo na subdoméně obsahovalo i speciální znaky a budeme uvažovat pouze malá/velká písmena (anglické abecedy), čísla a délku hesla 15 znaků, tak se jedná o 62^15, což je 768.909.704.948.766.668.552.634.368 možných kombinací. Tj. nesmysl, jdeme dál.
Třetí teorie
Vzhledem k nepravděpodobné druhé teorii o cracknutí hesla při tak nízkém počtu požadavků jsme se rozhodli opustit tuto cestu. Vybrali jsme si možnost pokusu o útok na session cookie pomocí cracknutí seedů používaných při “náhodném” generování klíče session cookie.
Session cookie si představme jako časově omezený unikátní kód, který je přiřazen uživateli, a který po něm server vyžaduje při každém dotazu, aby si ověřil s kým komunikuje. Na základě zjištěných informací může uživateli přiřadit příslušná oprávnění a na základě toho umožnit či odepřít přístup k určitým funkcím serveru. Pokud session cookie někdo zjistí, je schopen velmi jednoduše provádět operace pod uživatelským účtem i bez znalosti hesla. Session cookie je nejčastěji na serveru uložen ve formě souboru v dočasném adresáři.
Domnívali jsme se, že generování náhodnosti session cookie má slabinu, a že je možné predikovat, jaká bude další vygenerovaná cookie. Rovněž tuto teorii jsme však velmi záhy opustili. Opět se v ní objevila jedna velká trhlina: Získáním seedů je útočník schopný generovat příslušné session cookies. Ale pouze za předpokladu, že má útočník možnost zjistit přesný čas přihlášení uživatele. Bez této informace by trvalo generování potřebné session cookie velmi dlouho. Navíc, pokud by daná session cookie expirovala, tento útok by se jednoduše nezdařil nikdy.
Je tomu pár týdnu, kdy byl zrovna touto slabinou postižen i redakční systém Drupal, používající funkci mt_rand() (algoritmus Mersenne twister), jenž není dostačující. Pro zájemce o tuto problematiku doporučujeme přečíst si následující studii zveřejněnou na webu konference BlackHat USA (PRNG: Pwning Random Number Generators).
Čtvrtá teorie
Čtvrtou a závěrečnou teorii jsme si rozebrali a ověřili mnohem lépe než tři předchozí. Útočník nemusel heslo crackovat. Stačilo mu využít vlastností sdíleného hostingu.
Velký počet hostingů používá pro ukládání session cookies jeden adresář pro celý server (většinou podadresář v /tmp). Tato cesta se definuje v PHP proměnné session_save_path. Session cookies se tak mísí dohromady ze všech domén v jediném adresáři. Tj. session cookie vygenerovaný na SP mohl mít cestu /tmp/sessions/abcdef1234 a cookie naprosto odlišného webu běžící na stejném serveru pak /tmp/sessions/uvwxyz1234. Samozřejmě, druhý web má možnost číst a v případě špatného nastavení serveru i modifikovat session cookie soubor patřící SP.
Jsem si více než jist, že v době migrace SP k našemu současnému poskytovateli vypadala session_save_path asi následovně: /tmp/apachetmp/security-portal.cz/. Jednoduše řečeno adresář pro session cookies byl jen pro naší doménu, což je bezpečné a ideální nastavení. Nevím kdy se cesta změnila, protože od té doby uběhlo asi pět let. Jisté však je, že během útoku byla již cesta změněná. Upřímně, změnu save_path člověk prakticky nikdy průběžně neověřuje.
A právě tady byl kámen úrazu. Session cookie totiž funguje jako OTP (One Time Password). Jak bylo zmíněno, pokud jej dokážete zjistit, vystupujete jako daný uživatel.
Z access logů jsme vyčetli, že útočníci věnovali zvýšenou pozornost i dalším webům na stejném serveru (pomocí refereru). Jeden se jim povedlo prolomit. Podle údajů od administrátora hostingu se jeden z útočníků pokoušel o dump databáze subdomény (adresu webu jsme změnili):
category/tmpl/image/adminer-3.3.4.php?server=%3A%2Ftmp%2Fmysql50.sock HTTP/1.1" 200 1512 "http://neznamyweb.sk/components/com_contact/views/category/tmpl/image/adminer-3.3.4.php?server=%3A%2Ftmp%2Fmysql50.sock&username=bflow_security_portal_cz&db=bflow_security_portal_cz&select=bflow_users" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0"
Dump se nezdařil, avšak přes tento kompromitovaný web si mohli jednoduše vypsat všechny session cookies, které byly uloženy na serveru a klasickou cestou “pokus - omyl” testovali každou session cookie vůči naší subdoméně, dokud se jim nepovedlo přihlásit se do administrace. Bohužel, RubberDuck se ten den kolem desáté večer na danou subdoménu opravdu přihlásil a pracoval s ní. Po skončení práce však oproti všem jeho zvyklostem místo odhlášení jednoduše zavřel prohlížeč. Tím zůstala tato jediná session cookie aktivní.
Zkuste si i vy vypsat seznam session cookie na sdíleném hostingu pomocí tohoto jednoduchého scriptu:
$sessions = array();
$path = realpath(session_save_path());
$files = array_diff(scandir($path), array('.', '..'));
foreach ($files as $file)
{
$sessions[$file] = unserialize(file_get_contents($path . '/' . $file));
}
echo '<pre>';
print $path;
echo '<br />';
print_r($sessions);
echo '</pre>';
?>
V době analýzy útoku existovalo v našem session_save_path adresáři přibližně pět tisíc souborů = sessions.
A pak už to bylo více než jasné.
Útočník měl plný přístup k jinému webu běžícímu na stejném serveru jako SP, kde si prostě vypsal seznam existujících session cookies a zkoušel se pomocí každé z nich přihlásit do administrace subdomény, což mu na nějaký 3500-tý pokus vyšlo. Mazané.
Způsobů jak získat session cookie (session hijacking) je poměrně dost a pěkný souhrn metod naleznete na SP v článcích z roku 2006 od uživatele c0stra:
Advanced session stealing (část 1.)
Advanced session stealing (část 2.)
O problematice session cookies a o tom jak by mělo správně vypadat jejich používání, ukládání a nastavení PHP najdete na blogu Acunetix.
Proč byl cílem útoku SP?
Po několika hodinách jsme díky logům serveru přišli na fakt, že web security-portal.cz byl vybrán jako cíl útoku v rámci hackerské soutěže jednoho nejmenovaného arabského fóra. Ani jsme netušili jak jsme populární :)
Poté jsme z cca měsíc starých logů rozpoznali IP útočníků, kteří si nás před útokem oťukávali.
Celá hra měla následující formu: V rámci fóra vzniklo pět týmů (team1 až team5). Každý tým měl stejný úkol. Dostat se jakkoliv na vybrané servery a umístit na ně kontrolní soubor ve tvaru team(číslo).txt. Paradoxně si asi většina týmů nechávala zadní vrátka pro pozdější návrat do systému. Ať už byl jejich pozdější záměr jakýkoliv, souhrou náhod se nám útok podařilo eliminovat relativně rychle a čistě.
Závěr?
Nevím, zda jste někdy měli možnost vidět některý z dílů seriálu Dr. House, ve kterém hlavní hrdina vykonstruuje složitou souhru náhod, která dokonale vysvětluje všechny příznaky pacienta a následně pak zjistí, že to všechno bylo úplně jinak. Přesně to se stalo i nám. Oddechli jsme si, když jsme došli k tomu, že útočníci použili session cookies, napsali první díl seriálu a přibližně po měsíci se chystali napsat díl druhý. Chtěl jsem však ještě napsat vývojářům WP, aby do session cookies přidali validování zdrojové IP adresy, čímž by se stal tento útok neúčinným a na sdíleném hostingu by došlo ke zvýšení bezpečnosti všech WP.
Byl jsem však vyveden z omylu Samuelem Woodem ze security teamu WP, který mi sdělil, že WP vůbec nepoužívá PHP session cookie ani nikde ve zdrojovém kódu nepoužívá funkci session_start(). Tímto nás zcela zaskočil a celá naše představa o vektoru útoku byla pryč.
WP používá pseudo “session cookies” poměrně neobvyklým způsobem. Nejsou nikde uložené (soubor, databáze, ...) a generují se jen na základě hashe User ID, několikrát hashovaného fragmentu hesla uživatele, bezpečnostními klíči dané instalace WP a datu expirace cookie.
Na základě těchto skutečností nemohli útočníci použít výpis adresáře session_save_path a my jsme opět na začátku. Tedy ne tak docela, spíše v koncích, protože nemáme přístup k systémovým logům a nejsme tedy schopni dohledat, co přesně se v inkriminovaný večer událo. Zavedli jsme protiopatření, které již stejný útok dokáže zablokovat, i když neznáme přesný vektor. Pokud by i přesto byl útočník úspěšný, naše další opatření mu zabrání dostat se ze subdomény.
Je několik dalších možných vysvětlení, ale z námi dostupných dat nejsme schopni učinit jakýkoliv závěr bez spekulací.
Jak útokům předcházet?
Stejně jako u ostatních systémů musíte identifikovat hrozby a slabiny ve všech vrstvách. Míra zabezpečení jde ruku v ruce s cenou dat, která se snažíte chránit. Pokud únik dat může vaši společnost stát např. 100 milionů, asi nemá smysl designovat infrastrukturu za 120 milionů. I s pár servery a open source řešením jste schopni rapidně zvýšit míru bezpečnosti. Upřímně, je jen málo společností, kde bezpečnost řeší svědomitě. I proto je většina z nich relativně snadno napadnutelná a doposud jen měli štěstí, protože se pro nikoho nestali zajímavým cílem. Pokud čtete pravidelně seriál “Postřehy z bezpečnosti”, víte, že každý den podlehne útoku alespoň jedna velká společnost.
Protože popis zabezpečení každé vrstvy by vydal na samostatný článek, budu vše popisovat spíše bodově s odkazem na zdroj, kde se případný zájemce dozví podrobnosti, či postupy, jak zvýšit bezpečnost.
Bezpečnost sítě
Na sdíleném hostingu do bezpečnosti síťových prvků nebudete mít možnost mluvit, ale pokud máte to štěstí a server je např. umístěn ve vaší privátní síti, určitě bych doporučil:
- Aktualizovat firmware, či operační systém všech sítových prvků na poslední verzi
- Implementovat Intrusion Prevention System
- Nastavit síťové prvky tak, aby dokázali zamezit DoS/DDoS útokům
Bezpečnost serveru
- Aktualizovat všechny systémové balíčky na poslední verzi
- Postupovat podle příruček k vaší distribuci a změnou systémových parametrů zvýšit bezpečnost
- Zabezpečit Apache server
- Zabezpečit PHP
- Zabezpečit MySQL
- Změnit parametry jádra pro vyšší bezpečnost a výkon
- Použít multi-level security systém jako grsecurity
- mod_security [2] pro detekci SQLi, XSS, XSRF, RFi, LFi, DoS/DDoS apod. útoků
- mod_evasive pro základní detekci DoS/DDoS
- mod_spamhaus pro blokování IP adres spammerů, infikovaných počítačů a veřejných proxy serverů
- mod_ruid2 pro běh skriptů pod různými účty
- Linux Malware Detect, který dokáže odhalit webshelly, backdoory, obfuskované scripty, spolupracuje s AV programy a má i podporu monitorování adresářů
Bezpečnost webové aplikace
- Aktualizujte na poslední dostupnou verzi CMS
- Existuje spousta příruček o bezpečnosti pro každý CMS. Použijte je: Drupal, WordPress, Joomla, …
- Použijte moduly/pluginy, které dokáží dodatečně zvýšit bezpečnost a detekovat např. SQLi, XSS, CSRF, RFi/LFi, Bruteforce útoky, aplikační DoS útoky, vynutit potvrzení pomocí captcha, detekce spam postů, …
- Pokud jde o vaši vlastní aplikaci, tak ji podrobte analýze zdrojového kódu a penetračním testům
- Dělejte SHA256 checksum souborů vaší aplikace a nechte si zasílat emailem provedené změny a nové soubory
Logy serveru
V bezpečnosti víc než kde jinde platí, že musíte bezpečně ukládat logy a logovat vše, co je jen trochu možné, jinak jste víceméně slepí a nedokážete rozeznat, co přesně útočník v systému dělal nebo o co se pokoušel.
Užitečné je logy rovnou odesílat na centrální server sbírající tyto údaje z mnoha zařízení v síti, případně napojení na SIEM, který vás dokáže upozornit na začínající, či probíhající útok pomocí korelace logů z několika míst a systémů.
Pro detekci anomálií a útoků na webové servery existují i specializované nástroje a jedním (dle mého názoru) velice schopným se zdá být LORG, používající signatury, statistiku a učící se mechanismy pro odhalení útoků na vaše webové aplikace. Přednášku autora z konference Hack in Paris 2013 si můžete pustit na YouTube (PDF).
K tomu všemu musíte mít systém, který je schopen validovat nastavení, která jste zavedli, jako například CFEngine.
Neříkali jsme, že to bude jednoduché :)
Nakonec bychom chtěli poděkovat Františkovi Drojákovi z WebSupportu za pomoc při obnově a analýze a Samuelovi Woodovi z WP Security za konzultaci
Vzkaz pro útočníky (oni už budou vědět) - thanks4ever! :)
- Pro psaní komentářů se přihlašte
Occamova břitva
Udělali to IMHO takto jednoduše:
1. přes hacknutí jiného nezabezpečeného webu na sdíleném hostingu si povolili spuštění CGI skriptů
2. Pomocí CGI skriptu, na který se logicky nevztahují restrikce PHP, si přečetli přístupy do databáze v konfiguračním souboru WP wp-config.php
3. v databázi přepsali hash hesla uživatele admin za jim známou hodnotu
4. přihlásili se jako admin s novým heslem - WordPress, byť má jiné klíče a salty ve wp-config.php, toto umožňuje
O žádné sofistikované prolamování sezení tedy (podle mého skromného názoru) nešlo, nebo by alespoň byli idioti, kdyby to dělali tak složitě, když to lze jednoduše výše uvedeným způsobem.
Diky za komentar a] hosting
Diky za komentar
a] hosting pouziva modul ruid, ktery si sami napsali http://websupport.sk/~stanojr/projects/mod_ruid/ takze i CGI bezi pod unikatnim uzivatelem
b] heslo zustalo stejne, takze ho ani neprepsali. pochybuji ze by ho prepsali a pak vratili zpet, kdyz tam okolo zanechali takovou paseku.
c] security klice nejsou saltem hesla, ale pouzivaji se pro salt session cookie. kdyz je prepises, tak se jen zrusi vsechny sessions.
jinak souhlasim. nejspis se dostali k nam pres jiny web na stejnem serveru, pomoci vyuziti nektere zranitelnosti. pokud ano, tak uz zrejme nebude utok funkcni, protoze jsem to aktivne resil s hostingem a predpokladam, ze chybu napravili. tot prave moje spekulace, kterou jsem nechtel nikoho na stejnem hostingu plasit, pokud nemam dukaz.
.::[ optimista je člověk s nedostatkem informací.. ]::.
sed '66!d;s/[0-9]*\.\s*//;s/\./\!/' /usr/src/linux/M*
Dotaz
Vim ze je to as delikatni zalezitost, ale podelite se s nami s protiopatrenimi co jste zavedli? Jsem laik a premyslim o tom, zda zaridit vlastni server nebo nejaky serverovy prostor pronajmout. A protoze sdelujete informace o bezpecnosti tak me zajima reseni vaseho zabezpeceni, byt jste nezjistili jak se tam utocnik dostal.
Dekuji M
nastaveni
Dobry den,
vlastne jsme nastavili co bylo mozne v sekci "Bezpecnost webove aplikace", protoze ostatni sekce nejsme schopni ovlivnit + "-ExecCGI" pro vypnuti vsech CGI scriptu.
Staci takto?
Dekuji
.::[ optimista je člověk s nedostatkem informací.. ]::.
sed '66!d;s/[0-9]*\.\s*//;s/\./\!/' /usr/src/linux/M*
Další opatření
Dobrý den,
můžete nějak blíže vysvětlit to "naše další opatření mu zabrání dostat se ze subdomény"?
Děkuji.
Pěknej článek
Zajímavej článek a rozbor, díky