SQL injection

Z Wikipedie, otevřené encyklopedie

Skočit na: Navigace, Hledání

SQL injection je technika napadení databázové vrstvy programu vsunutím (odtud „injection“) kódu přes neošetřený vstup a vykonání vlastního, samozřejmě pozměněného, SQL dotazu. Toto nechtěné chování vzniká při propojení aplikační vrstvy s databázovou vrstvou (téměř vždy se totiž jedná o dva různé programy) a zabraňuje se mu pomocí jednoduchého escapování potencionálně nebezpečných znaků.

Obsah

[editovat] SQL injection a web

V klasickém případě je útok na internetové stránky prováděn přes neošetřený formulář, manipulací s URL nebo třeba i podstrčením zákeřně upravené cookie. Bohužel, na internetu je stále velké množství webů, spravovaných převážně nezkušenými programátory, kteří o této technice útoku prostě neví a tuto kritickou chybu opomíjejí.

[editovat] Ukázka útoku

Mějme program odesílající dotaz do databáze:

 statement := "SELECT * FROM uzivatele WHERE jmeno = '" + zadaneJmeno + "';"

Pokud však uživatel zadá jako jméno například:

a' or 'b'='b

aplikační program dotaz doplní a odešle databázi ve formě

 statement := "SELECT * FROM uzivatele WHERE jmeno = 'a' or 'b'='b';"

což může zapříčinit přemostění autorizační procedury, protože 'b' = 'b' je vždy pravda.

Pro SQL injection se samozřejmě dají použít všechny dostupné příkazy, pokud bychom tedy v předešlém příkladě jako jméno zadali

a';DROP TABLE uzivatele; --

vypadal by dotaz při odeslání serveru jako

 statement := "SELECT * FROM uzivatele WHERE jmeno = 'a';DROP TABLE uzivatele; --';"

čímž se nám povedlo smazat celou tabulku uživatelů. Poslední apostrof je pomocí sekvence – zapoznámkován a nemá žádý vliv.

Podobných průniků je samozřejmě celá řada, díky klauzulím UNION a JOIN nejsme ani vázáni na tabulku předepsanou v části FROM a můžeme vypisovat data odkudkoliv z databáze.

[editovat] Obrana

[editovat] Na straně aplikace

Nejjednodušší obrana spočívá ve vhodné kontrole a úpravě vstupních dat. Prakticky každý skriptovací program s podporou databáze má nějakou vestavěnou funkci pro převedení potenciálně nebezpečných znaků na bezpečnou sekvenci. Tuto funkci je možné použít před vytvořením dotazu.

Například pro Perl

 $query = $sql->prepare(
        "SELECT * FROM uzivatele WHERE jmeno = "
        .
        $sql->quote($zadaneJmeno)
   );

pro PHP (v příkladu implementace MySQL):

 $sql = "SELECT * FROM uzivatele WHERE jmeno = "
        .
        mysql_real_escape_string($zadaneJmeno);
 mysql_query($sql);

Dalším bezpečnostním opatřením (může se stát, že na ošetření vstupu někde prostě zapomeneme), je vypnutí vypisování chyb. Pokud by pak útočník na nějaký napadnutelný vstup narazil, nedozví se o tom z chybových hlášení.

[editovat] Na straně databáze

V databázi můžeme útoku zabránit (nebo ho přinejmenším extrémně ztížit) vhodným nastavením práv uživatele, se kterými bude program přistupovat. Málokdy je třeba přímo z aplikační vrstvy mazat tabulky či dokonce databáze, proto stačí povolit jen základní SQL příkazy.