Halloweenská akce! Na stránce s dobitím bodů zadej dole kód STRASIDELNYCH20 a získej porci +20% bodů zdarma!
Akce končí 31.10. o půlnoci.

Jak (si nechat) hacknout webovou aplikaci?

PHP Bezpečnost Jak (si nechat) hacknout webovou aplikaci?

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

Tento článek se vztahuje k březnovému přednáškovému srazu, kde jsem mluvil o nejběžnějších bezpečnostních chybách webových aplikací.

Zde na ITNetwork existuje několik detailnějších článků popisující jednotlivé chyby. Já bych rád shrnul ty nejčastější.

Napsal jsem testovací aplikaci nazvanou Super secure social network, která má sloužit jako ukázkový příklad špatně napsané PHP aplikace, ze které zde čerpám příklady. Tyto chyby se dají udělat i v jiných jazycích, zde budu však používat příklady z PHP.

Neošetřené uživatelské vstupy

Většina chyb a bezpečnostních děr vzniká, pokud útočník pošle na stránky vstup, který programátor neočekával a neošetřil. Ten může přijít z mnoha zdrojů:

  • GET
  • POST, tělo požadavku
  • Upload souborů

Je potřeba myslet na to, že nad tím, co uživatel posílá v požadavku na server, má kontrolu sám uživatel. Pokud provádíte jakékoliv validace v rámci prohlížeče, je následně potřeba provést je i na serveru. Např. pokud uživatel pošle formulář, měl by server umět pracovat se situací, kdy dostane jiná políčka, než očekával. Toho hezky využívá chyba Mass assignment.

SQL Injection

Představme si, že vytváříme sociální síť. U každého příspěvku je like tlačítko a po jeho stisknutí budeme chtít vložit do tabulky users_posts_like uživatelův like. Na to programátor naivně napíše podobný kus kódu:

"INSERT INTO users_posts_like (user_id,post_id) VALUES ({$_SESSION['id']},{$_GET['like']})"

Ten bude fungovat dobře, dokud uživatel v GET parametru nepošle něco jiného, než předpokládané číslo. Co kdyby uživatel poslal např. "?like=12); TRUNCATE TABLE users_posts_li­ke;/*"

Ten se vyhodnotí jako dva různé dotazy:

INSERT INTO users_posts_like (user_id,post_id) VALUES (123,12);
TRUNCATE TABLE users_posts_like;
/*)

První provede to, co programátor očekává. Druhý je zcela podstrčený útočníkem. Může jím provést cokoliv v databázi. V tomto případě smaže obsah celé tabulky users_posts_like.

Prepared statements

Pokud používáme PDO, či jinou DB vrstvu, umožňuje nám používat tzv. Prepared statements. Jedná se o techniku, kdy dotaz rozdělíme na dvě části - strukturu a data.

Nejdříve definujeme strukturu dotazu a místo dat dosadíme proměnné:

$query = $db->prepare("INSERT INTO users_posts_like (user_id,post_id) VALUES (:user_id,:post_id})");

Následně řekneme, jaká data mají v proměnných být:

$query->bindParam(':user_id', $_SESSION['id']);
$query->bindParam(':post_id', $_REQUEST['like']);
$query->execute();

Pokud máme v PDO vypnuté EMULATE_PREPARES, provede se dotaz na 2 části. Nejdříve je databázi poslaná struktura a až potom data, která nejsou v žádném případě braná jako struktura dotazu.

Pokud máme EMULATE_PREPARES zapnuté PDO nám parametry automaticky escapuje.

Escapování

Pokud použáváme zastaralé mysql funkce, můžeme vstupy od uživatele ručně ošetřit pomocí "mysql_real_es­cape_string": http://php.net/…e-string.php. Toto řešení je však náchylné k udělání chyby.

XSS

Je zkratka pro Cross-site scripting. Tato bezpečností díra nespouští kód na serveru, ale JavaScript na straně uživatele. Představme si, že na naší sociální síti máme příspěvky, které se na zeď vypisují takto:

$query = $db->prepare("SELECT content FROM posts");
$query->execute();
$result = $query->fetchAll();
foreach($result as $row){
    echo $row['content'];
    echo '<hr/>'
}

Pokud někdo do příspěvku umístí např.:

ahoj
<script>alert("baf!");</script>

Bude příspěvěk působit jako obyčejné ahoj. Avšak všem lidem na stránce bude při příchodu vyskakovat "baf!". To by bylo spíše otravné než nebezpečné. My ale pomocí skriptu můžeme provádět opravdu mnoho věcí např.:

  • Nastavit listenery na políčko jména a hesla a to si posílat na vlastní server.
  • Uživatele přimět zadat mail v domění, že ho posílá napadená stránce.
  • Můžeme celou stránku zcela předělat.
  • Můžeme si od uživatele poslat všechna cookies, co nejsou HttpOnly.

Jakmile objevíme XSS díru, můžeme stránku narušit mnoha kreativními způsoby. Dokonce existuje nástroj, který se dá použít na vzdálené ovládání otevřených napadených stránek - Beef framework.

Escapování

Nejjednosušší cestou, jak tuto chybu neudělat, je escapování. K tomu nám pro HTML v PHP slouží funkce htmlspecialchars. Problém je, že když escapujeme v jiném kontextu (např. atributu), musíme použít jinou funkci či dokonce jejich kombinaci. Je velmi lehké splést se a XSS díru udělat omylem.

Šablonovací systémy

Nejlepší cestou, jak se této chyby nedopustit, je použít nějaký šablonovací systém v PHP např. Twig, Smarty či Latte.

CSRF

Cross-site Request Forgery je provedení požadavku za jiného uživatele bez jeho vědomí. Představme si, že like tlačítko na naší sociální síti bude vypadat takto:

<a href="?like=27">Like</a>

Co kdybychom vyrobili link pomocí zkracovače odkazů směřující na supesecuresoci­alnetwork.fake/wa­ll?like=27 a ten poslali na tuto sít. Každý, kdo by na daný odkaz klikl, by automaticky olikoval nás příspěvek.

A co kdybychom kreativně zkombinovali CSRF a XSS. Místo postu, co hází Baf!, bychom poslali post:

ahoj
<img src="https://supesecuresocialnetwork.fake/wall?like=27" style="display:none"/>

V tuhle chvíli by uživatelé likovali náš příspěvek bez toho, aby provedli jakoukoliv akci, kromě zobrazení nejnovějších příspěvků.

POST vs. GET

Podstata této chyby spočívá v tom, že můžu provést akci pomocí metody GET. Správně navržená webová aplikcace by měla měnící akce posílat pouze pomocí metody POST (případně PUT, DELETE,...). Metoda GET by se měla používat pouze pro požadavky, kdy informace tečou ze serveru ke klientovi a nic na serveru nemění (kromě logů a zaznamenání návštěvnosti).

Další

Mnoho věcí jsem zde nezmínil a zmíním v dnešní přednášce a následně je doplním sem nebo do dalšího článku:

  • Clickjacking
  • Špatné a správné ukládání hesel
  • HTTP(S) a downgrade útoky a obrana pomocí HSTS
  • DDoS
  • Phishing

 

 

Článek pro vás napsal Pavol Hejný
Avatar
Jak se ti líbí článek?
7 hlasů
/^(web )?(app )?developer$/
Miniatura
Předchozí článek
Obrana proti útoku XSS v PHP
Miniatura
Všechny články v sekci
Bezpečnost webových aplikací v PHP
Aktivity (7)

 

 

Komentáře

Avatar
Šimon Rataj
Člen
Avatar
Šimon Rataj:30. března 19:10

Avšak všem lidem na stránce bude při příchodu vyskakovat "ahoj".

Nebude jim tam spíše vyskakovat "baf!"?

 
Odpovědět  +3 30. března 19:10
Avatar
Pavol Hejný
Autoredaktor
Avatar
Odpovídá na Šimon Rataj
Pavol Hejný:31. března 2:22

Dík za upozornění na chybu, je to opraveno.

Odpovědět 31. března 2:22
/^(web )?(app )?developer$/
Avatar
Marek Mozola
Člen
Avatar
Marek Mozola:1. dubna 16:49

Ako sa rieši ak do databáze vkladáme napr. výstup z froaly alebo nejakého wysiwyg editoru? V tom prípade to escapovať nemôžeme, alebo sa mýlim?

 
Odpovědět 1. dubna 16:49
Avatar
albertpatera
Redaktor
Avatar
Odpovídá na Marek Mozola
albertpatera:1. dubna 17:45

Ahoj, řeší se to tak, že každý editor ma nějaké sve specifické značky,které symbolizují HTML tagy, např. Jako zde ** ** ** symbolizuje tag b .

 
Odpovědět 1. dubna 17:45
Avatar
berykubik
Redaktor
Avatar
Odpovídá na Marek Mozola
berykubik:6. dubna 14:22

Popř. jestli jsi odvážný, můžeš jít cestou HTML whitelistu :-)

 
Odpovědět 6. dubna 14:22
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 5.