Save 37% off PRO during our Black Friday Sale! »

Bezpečnost webových aplikací

Bezpečnost webových aplikací

Popis několika základních útoků na webové aplikace, metody obrany proti těmto útokům, s ukázkami v PHP a Pythonu. Trocha doporučení k ukládání hesel.

F110ecff96cffca147a6985f4ef5cb72?s=128

Michal Špaček

September 27, 2012
Tweet

Transcript

  1. Michal Špaček Nebezpečné PyVo, 27. 9. 2012, Brno Varování: obsahuje

    nejen PHP, ale i příklady pro Python www.michalspacek.cz @spazef0rze WEB
  2. Michal Špaček www.michalspacek.cz Ú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.
  3. Michal Špaček www.michalspacek.cz 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.
  4. Michal Špaček www.michalspacek.cz V PHP to může 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.
  5. Michal Špaček www.michalspacek.cz Příklad z Pythonu pak vypadá třeba takto.

    Z této chybové hlášky se dozvíte nejenom použitý operační systém, seznam funkcí, které byly volány, ale třeba i adresu Redis serveru, ke kterému se zrovna nepovedlo připojit.
  6. Michal Špaček www.michalspacek.cz Jednou z několika možností, jak v PHP

    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í.
  7. Michal Špaček www.michalspacek.cz 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.
  8. Michal Špaček www.michalspacek.cz Ř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.
  9. Michal Špaček www.michalspacek.cz 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.
  10. Michal Špaček www.michalspacek.cz DEBUG = False V Djangu pak nezapomeňte

    vypnout debug mód. Některé další frameworky, jako třeba Bottle nebo Flask ho mají standardně vypnutý. Pokud používáte nějaký jiný framework, vždy se přesvědčte, jak je nastaven.
  11. Michal Špaček www.michalspacek.cz 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/
  12. Michal Špaček www.michalspacek.cz Ú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 a taky toho, že toto není PHP stránka.
  13. Michal Špaček www.michalspacek.cz 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.
  14. Michal Špaček www.michalspacek.cz 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.
  15. Michal Špaček www.michalspacek.cz Řešení? framework V Pythonu (a asi i

    v PHP) je nejlepší možné řešení použít nějaký framework na vypisování dat (nebo aspoň nějaký šablonovací systém). Pro jistotu se ale stejně podívejte, jak vlastně pracuje, jestli pro prevenci XSS není potřeba nějaké speciální nastavení.
  16. Michal Špaček www.michalspacek.cz Řešení? htmlspecialchars($string) Další jednoduché řešení pro PHP.

    Pro ochranu před XSS stačí veškerá data (uživatelská i aplikační), která do HTML vypisujeme, nejdříve prohnat skrz tuto funkci. Na výpis do JavaScriptu, který má jiné speciální znaky (trackovací kódy např.) použijte třeba json_encode().
  17. Michal Špaček www.michalspacek.cz 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.
  18. Michal Špaček www.michalspacek.cz String.encode('ascii', 'xmlcharrefreplace') Jestli chcete v Pythonu zažít

    středověk nebo si píšete nějaký vlastní šablonovací systém nebo framework (dělá to v Pythonu někdo?), tak použijte pro ošetření výstupu proti XSS tuhle metodu třídy String.
  19. Michal Špaček www.michalspacek.cz 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.
  20. Michal Špaček www.michalspacek.cz Nepoužívat lxml / BeautifulSoup proti XSS Stejně

    tak v Pythonu nepoužívejte na ochranu před XSS nástroje a třídy jako jsou lxml nebo BeautifulSoup. Ty slouží na parsování a filtrování XML nebo HTML a přesto že to dělají na jedničku, tak to není ten správný nástroj na ochranu proti XSS.
  21. Michal Špaček www.michalspacek.cz 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.
  22. Michal Špaček www.michalspacek.cz Ú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.
  23. Michal Špaček www.michalspacek.cz "… WHERE znacka = '%s'" % request.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í. Původně to byl PHP skript, ale naznačen je kód v Pythonu, který je chybně napsán a umožňuje provést SQL Injection útok.
  24. Michal Špaček www.michalspacek.cz 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á.
  25. Michal Špaček www.michalspacek.cz 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. '… WHERE id = %s' % request.GET['id']
  26. Michal Špaček www.michalspacek.cz Ř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.
  27. Michal Špaček www.michalspacek.cz 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.
  28. Michal Špaček www.michalspacek.cz mysql_set_charset() mysql_real_escape_string() Rozšíření mysql v PHP 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 25, 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. Pro ochranu v tomto případě zvolíme přetypování na integer.
  29. Michal Špaček www.michalspacek.cz Python? oursql, MySQLdb, psycopg2, SQLAlchemy Pro Python

    existuje spousta oblíbených rozšíření pro práci nejen s MySQL (psycopg2 je pro PostgreSQL), které prepared statements řeší. Použít lze i ORM nástroje, u kterých je ale obrana proti SQL Injection spíše takovým vedlejším efektem.
  30. Michal Špaček www.michalspacek.cz oursql cursor.execute( "SELECT id FROM users WHERE

    user = ? AND password = ?", (user, password)) V rozšíření oursql se dotazy spouštějí takto. Důležité jsou otazníky, kolem kterých nejsou žádné uvozovky, tzv. placeholdery a to, že se vlastní hodnoty do metody execute předávají jako její další parametr.
  31. Michal Špaček www.michalspacek.cz psycopg2 cursor.execute( "SELECT id FROM users WHERE

    user = %s AND password = %s", (user, password)) V psycopg2 pro PostgreSQL je to podobné, s tím rozdílem, že se zde používá %s jako placeholder. Jedná se opravdu jenom o %s a ne třeba o %d, jak by se mohlo zdát, že by mohlo fungovat. Vlastní hodnoty jsou do execute opět předány jako další parametr.
  32. Michal Špaček www.michalspacek.cz Nikdy! cursor.execute( "SELECT id FROM users WHERE

    user = '%s' AND password = '%s'" % (user, password)) Mohlo by se stát, že se vývojář splete a místo poslání hodnot ve zvláštním parametru je vlepí přímo do dotazu samotného. Stačí taková drobnost, jako zaměnit čárku (,) se znakem procenta (%), naštěstí jsou na klávesnici docela daleko od sebe. Pozor na to!
  33. Michal Špaček www.michalspacek.cz ' OR 1 -- - SELECT id

    FROM users WHERE user = '' OR 1 -- -' AND password = '…' Kdyby totiž někdo zadal místo svého jména něco jako ' OR 1 -- -, tak se spustí tento dotaz, který vrátí všechny id z databáze, cokoliv OR 1 je totiž vždy pravda a podmínka na heslo je zakomentovaná. (V MySQL začíná komentář do konce řádku znaky pomlčka pomlčka mezera)
  34. Michal Špaček www.michalspacek.cz Použitelnost McDonald's & O'Reilly Nejedná se ale

    jenom o bezpečnost, ačkoliv kvůli té si asi tyto slajdy čtete primárně. Pokud by se do vaší aplikace chtěl zaregistrovat někdo z výše uvedených pánů, tak má smůlu, kvůli speciálním znakům ve jménech jim to nepůjde. Vy s vaší aplikací jste tak promarnili životní šanci.
  35. Michal Špaček www.michalspacek.cz 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.
  36. Michal Špaček www.michalspacek.cz 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.
  37. Michal Špaček www.michalspacek.cz 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.
  38. Michal Špaček www.michalspacek.cz Řešení? 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ě. Pro šifrování v Pythonu použijte třeba hashlib nebo rozšíření PyCrypto. SHA-512 a salt? hashlib, PyCrypto
  39. Michal Špaček www.michalspacek.cz Lepší řešení? 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, v Pythonu lze využít implementaci py-bcrypt. Tento hash doporučuje váš dealer! bcrypt! Blowfish hashing, py-bcrypt http://codahale.com/how-to-safely-store-a-password/
  40. That's it. That's me. Díky Martinovi Čarnogurskému za pomoc s

    příklady z Pythonu. 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!