Útoků na webové aplikace existují desítky. Představíme si tři základní, ukážeme si, jak takový útok provést a jak webovou aplikaci proti danému útoku zabezpečit. Na závěr si ukážeme, jak bezpečně ukládat uživatelská hesla a pár špeků, kterým byste se měli obloukem vyhnout.
2. Útoky na web
SQL Injection
Cross-Site Scripting
Full Path Disclosure
Útoků na webové aplikace existují desítky. Local File Inclusion, Remote Code Execution a další.
Povíme si o těchto třech, kde první dva jsou navíc velice závažné. Všechny tři mají jednu
společnou věc – zabránění těmto útokům je jednoduché, jak facka.
Michal Špaček www.michalspacek.cz
3. Full Path Disclosure
Vyzrazení plné cesty ke skriptu
http://devblog.cz/2012/04/fpd-aneb-full-path-disclosure/
Začneme od konce. Full Path Disclosure (FPD) je útok, kterým donutíte webovou aplikaci, aby
vyzradila kde na disku serveru jsou uloženy skripty dané aplikace. Více o FPD si můžete přečíst v
mém článku na uvedené adrese.
Michal Špaček www.michalspacek.cz
4. Může to vypadat třeba takto. Aplikace nám toho ovšem vyzradí mnohem více, než jen to, kde na
disku žije. Dozvíme se například operační systém serveru, zjistíme, že je povolené zobrazování
chybových hlášek a z adresářové struktury odhadneme, že to nepoužívá Nette.
Michal Špaček www.michalspacek.cz
5. Jednou z několika možností, jak tento útok vyvolat, je změna typu vstupních parametrů. Z
klasického řetězce uděláme pole přidáním hranatých závorek za název parametru v URL (a před
rovnítko). Některé funkce však umí pracovat jenom s řetězcem a náležitě nám to oznámí.
Michal Špaček www.michalspacek.cz
6. Další variantou FPD útoku je zobrazení výstupu phpinfo(). Na velké části webů psaných v PHP
se takový výstup nachází na URL /info.php nebo /phpinfo.php. Tyto informace obsahují
třeba i čísla verzí nebo kompletní nastavení PHP. Nikdy toto nedávejte na produkční servery.
Michal Špaček www.michalspacek.cz
7. Řešení?
display_errors = Off
Říkal jsem, že řešení jsou jednoduchá, že? Zakažte zobrazování chybových hlášek a hotovo.
Hlášky si samozřejmě nesmíte vypisovat sami, třeba v nějakém error handleru. Zobrazování
zakažte pokud možno už v .htaccess pomocí php_flag display_errors off.
Michal Špaček www.michalspacek.cz
8. log_errors = On
Co naopak povolte, je ukládání chybových hlášek do nějakého souboru, abyste se vůbec
dozvěděli, že k nějakým chybám dochází. To provedete také nejlépe v souboru .htaccess takto:
php_flag log_errors on, chybové hlášky pak naleznete v error logu serveru.
Michal Špaček www.michalspacek.cz
9. Cross-Site Scripting (XSS)
Útočník vloží na naši stránku
vlastní JavaScript
Zábavnějším útokem na webové aplikace a na jejich návštěvníky je Cross-Site Scripting. Útočník
vložením vlastního JavaScriptu do stránky získává kontrolu nad prohlížečem návštěvníka. Může s
ním dělat vše, co JavaScript dovoluje, inspirujte se třeba projektem BeEF http://beefproject.com/
Michal Špaček www.michalspacek.cz
10. Úspěšný útok Cross-Site Scripting může vypadat třeba takto. Toto je pouze Proof-of-Concept kód,
načítající JavaScript z cizího serveru, zobrazení identifikátoru session nemá žádný praktický
dopad. Všimněte si hodnoty parametru zb v URL adrese.
Michal Špaček www.michalspacek.cz
11. Všimněte si označeného textu. Tento HTML tag vložil útočník úpravou adresy stránky (viz
předchozí obrázek) a webová aplikace jej zapomněla zabezpečit. Útočníkovi pak stačí takovou
adresu (třeba zkrácenou pomocí TinyURL) poslat oběti, této variantě se říká Reflected XSS.
Variantě, kdy útočník vloží HTML značky například do diskuzního příspěvku a aplikace jej neošetří
říkáme Permanent XSS, protože je zkrátka permanentní, útočník nemusí upravovat odkaz a nic
nemusí nikomu posílat, stačí jenom navšívit takovou napadenou stránku.
Michal Špaček www.michalspacek.cz
12. Pomocí vloženého JavaScriptu může útočník dělat spoustu věcí, zde je například ukázka
odchytávání uživatelských jmen a hesel zadávaných do formuláře s id userform a jejich
odesílání na server tak, aby uživatel nic nepoznal, formulář se následně normálně odešle.
Michal Špaček www.michalspacek.cz
13. Řešení?
htmlspecialchars($string)
Další jednoduché řešení. Pro ochranu před XSS stačí veškerá data (uživatelská i aplikační), která
do HTML vypisujeme, nejdříve prohnat skrz uvedenou funkci. Na výpis do JavaScriptu, který má
jiné speciální znaky (trackovací kódy např.) použijte třeba json_encode().
Michal Špaček www.michalspacek.cz
14. htmlspecialchars($string, ENT_QUOTES)
htmlspecialchars() standardně převádí na HTML entity pouze znaky &, ", < a >. Pokud
HTML atributy uzavíráte do jednoduchých uvozovek, musíte přidat flag ENT_QUOTES.
Nejjednodušší je ale použít nějaký šablonovací systém, který celé escapování řeší za vás.
Michal Špaček www.michalspacek.cz
15. Nepoužívat
strip_tags()
proti XSS
Nikdy nepoužívejte na ochranu před XSS funkci strip_tags(). Není na to určená a navíc
neochrání před tím, když útočník nebude vkládat celé tagy, ale jenom nové atributy (třeba
onmouseover). Nepoužívejte ji ani na povolení některých tagů, ponechává totiž tagy i atributy.
Michal Špaček www.michalspacek.cz
16. SQL Injection
Útočník modifikuje SQL dotaz
Dopad útoku SQL Injection může být poměrně značný. Pokud je úspěšný, tak má útočník pod
kontrolou celou databázi webové aplikace a může si s ní dělat, co chce. Například získávat
uživatelská jména a hesla nebo finanční výsledky majitele. A taky měnit uložená data, třeba ceny.
Michal Špaček www.michalspacek.cz
17. Útok spočívá v úpravě SQL dotazu, který aplikace odesílá do databázového serveru. Napsáním
speciálních znaků do některého parametru v adrese (zde znacka) vyvoláme chybu a zkoumáním
a hledáním zadaného řetezce (třetí řádek shora, vpravo) zjistíme, jak parametr upravit.
Michal Špaček www.michalspacek.cz
18. "… WHERE znacka = '{$_GET['znacka']}'"
Chyba vyvolaná na této stránce vznikla nejspíš tak, že parametr znacka byl rovnou vložen do
SQL dotazu, mezi jednoduché uvozovky, bez nějakého ošetření. Naznačen je kód v PHP skriptu,
který je chybně napsán a umožňuje provést SQL Injection útok.
Michal Špaček www.michalspacek.cz
19. Zde vidíme podobnou chybu, jako na předchozím obrázku. Parametr id původně obsahoval
nějaké číslo, ale uvedením řetezce se útočníkovi podařilo vyvolat tuto chybovou hlášku, kterou na
sebe aplikace vyzradila, že útoku SQL Injection neodolá.
Michal Špaček www.michalspacek.cz
20. '… WHERE id = ' . $_GET['id']
Kód ve skriptu vypadal nejspíš nějak takto. Parametr id je rovnou připojen na konec SQL dotazu,
není uzavřen v jednoduchých uvozovkách a proto si databázový server myslí, že je to název
sloupce. I bez zobrazeného SQL dotazu útočník dokáže odhadnout, co má do parametru vložit.
Michal Špaček www.michalspacek.cz
21. Řešení?
Prepared statements (PDO)
V případě ochrany proti SQL Injection je řešení trochu náročnější. Místo skládání řetězců
oddělíme odesílání SQL kódu od dat a nemůže se tedy stát, že modifikací dat změníme kód. V
PHP toto elegantně řeší extenze PDO. Někdy se můžete setkat s termínem vázání proměnných.
Michal Špaček www.michalspacek.cz
22. Takto nějak vypadá práce s rozšířením PDO. Na řádku 2 vytvoříme spojení s databázovým
serverem. Na řádku 3 je pak uveden SQL dotaz a místo hodnot jsou uvedena zástupná jména
parametrů ve formátu :jmeno. Na řádku 4 řekneme databázovému serveru, aby si připravil
vykonání dotazu. Metodou bindValue() propojíme zástupné jméno s hodnotou, všiměte si, že
hodnotu nikde nijak speciálně neošetřujeme a že v dotazu nejsou kolem :id uvozovky. Na řádku
6 konečně odešleme data na databázový server a tím efektivně vykonáme dotaz.
Michal Špaček www.michalspacek.cz
23. mysql_set_charset()
mysql_real_escape_string()
Rozšíření mysql vázání proměnných nijak elegantně nepodporuje. Pro ošetření hodnot v SQL
dotazu pak musíme použít funkci mysql_real_escape_string() a nesmíme po připojení
zapomenout zavolat mysql_set_charset(). Uvedené řešení ovšem nevyřeší problém, který je
ukázán na stránce 20, tedy případ, kdy v SQL dotazu očekáváme číslo. Tyto funkce slouží k
zabránění „útěku z řetezce“, ale pokud v dotazu očekáváme číslo, tak v žádném řetezci nejsme a
nemusíme tedy z ničeho utíkat. Pro ochranu v tomto případě zvolíme přetypování na integer.
Michal Špaček www.michalspacek.cz
24. Nepoužívat
addslashes()
proti SQLIA
Vůbec nikdy nepoužívejte funkci addslashes() pro ošetření dat proti SQL Injection Attack.
Tato funkce, ač zdánlivě dělá to samé, tak neslouží pro ochranu proti SQL Injection. V MySQL v
některých asijských znakových sadách je i přes použití addslashes() možné SQLIA provést.
Michal Špaček www.michalspacek.cz
25. Hashování hesel
Nepoužívat MD5
Ani SHA-1
Pokud v aplikaci ukládáte hesla uživatelů, nikdy je neukládejte jen tak, v čitelné podobě. Hashujte
je před uložením do databáze. Ovšem není hashování, jako hashování. Pro nové aplikace dnes
už nepoužívejte MD5 ani SHA-1 a to ani pokud hashujete vícenásobně a už vůbec ne bez saltu.
Michal Špaček www.michalspacek.cz
26. Jak MD5, tak SHA-1 jsou už překonané. Předpočítané hashe najdete na webu Googlem, takže
nemusíte nic crackovat. A když nic nenajdete, tak oba algoritmy jsou tak rychlé, že cracknutí hesel
je většinou otázka několika minut.
Michal Špaček www.michalspacek.cz
27. Řešení?
SHA-512 a salt?
hash_hmac()
Pokud budete hashovat hesla, tak používejte minimálně SHA-512 a rozhodně je nutné použít salt
jako obranu proti Birthday attacks. Salt může být uložen v databázi ve speciálním sloupci, v
čitelné podobě. Hash počítejte HMAC algoritmem, můžete také použít opakované hashování.
Michal Špaček www.michalspacek.cz
28. oclHashcat
md5($pass.$salt)
md5($salt.$pass)
sha1($pass.$salt)
sha1($salt.$pass)
Nepoužívejte salt uvedeným způsobem, tedy pouhým přidáním za heslo. Salt je uložen v databázi
společně s heslem a použitý „algoritmus“ se dá odhadnout nebo vyčíst ze zdrojových kódů.
Nástroje na crackování hesel (třeba rychlý oclHashcat) s tímto způsobem saltování umí zacházet.
Michal Špaček www.michalspacek.cz
29. Lepší řešení?
bcrypt!
crypt() + Blowfish hashing
http://codahale.com/how-to-safely-store-a-password/
Existuje ale lepší řešení a opět jednoduché, vícenásobné hashování i obranu proti hrubé síle díky
relativní vlastní pomalosti vyřeší použití funkce crypt() s Blowfish hashing algoritmem, který se
zapne saltem, který začíná na $2y$, tato možnost je dostupná v PHP 5.3.7 a novějším, varianta
$2a$ nefunguje zcela korektně, více v dokumentaci PHP. V PHP 5.5 jsou nové funkce
password_hash() a password_verify(), které vše elegantně řeší, do starších verzí je přidá
knihovna https://github.com/ircmaxell/password_compat. Blowfish hash doporučuje váš dealer!
Michal Špaček www.michalspacek.cz
30. Můžete si všechno správně zahashovat a ochránit proti všem možným útokům, ale když
zapomenete nějakou zálohu nebo logy na disku v adresáři, který je dostupný z prohlížeče a má
povolené vypisování obsahu (tzv. open dir), máte nemalý problém. To vypisování raději zakažte.
Michal Špaček www.michalspacek.cz
31. V přístupných a „otevřených“ adresářích se dá najít spousta věcí. Třeba statistiky zasílání
informačních e-mailů, včetně samotných e-mailových adres. Tohle na ulici nenajdete, databáze
ověřených adres lidí, kteří se zajímají o produkt, který web nabízí, stojí obvykle dost peněz.
Michal Špaček www.michalspacek.cz
32. robots.txt
Máte už plné zuby dobrých skutků, které jsou po zásluze potrestány? Napište evil bota, který
bude procházet soubory robots.txt a bude stahovat obsah, ke kterému mají roboti normálně
zakázán přístup. Ale pozor, budete mít opravdu mnoho opravdu zajímavých dat.
Michal Špaček www.michalspacek.cz
33. Uvidíte-li v robots.txt uvedeny adresáře jako jsou třeba tmp nebo logs (nebo obojí
dohromady) určitě se do nich podívejte. Když se to podaří a adresář prozradí svůj obsah, bude to
stát za to. Pamatujte, do robots.txt patří jen to, co nemají vidět roboti, ne lidé.
Michal Špaček www.michalspacek.cz
34. /.svn/entries
Děláte deployment z SVN? A máte na serveru kompletní working copy? A co se stane, když
server požádáte o soubor /.svn/entries? Když tento soubor dostanete, je velká
pravděpodobnost, že dostanete celou working copy v původní podobě, což znamená… zdrojáky!
Michal Špaček www.michalspacek.cz
35. http://hostname/.svn/text-base/index.php.svn-base
Subversion totiž ve working copy drží kopie původních souborů, které mají speciální koncovku,
takže většinou nejsou zpracovávány jako PHP skripty a server je normálně nabídne ke stažení.
Podívejte se do adresáře .svn a pak jej ze serveru smažte nebo aspoň do něj zakažte přístup.
Michal Špaček www.michalspacek.cz
36. That's it. That's me.
Michal Špaček
www.michalspacek.cz
@spazef0rze
Přijďte na školení
http://www.michalspacek.cz/skoleni
Tak a to je vše, přátelé. Sledujte mě na Twitteru https://twitter.com/spazef0rze, pokud se chcete
dozvědět, co se děje v mém světě PHP, bezpečnosti a výkonnosti. Pokud se toho chcete
dozvědět ještě více z uvedených oblastí, přijďte třeba na školení, která vedu. Díky a zas někdy!