SQL injection
Jste-li s popisovaným předmětem seznámeni, pomozte doložit uvedená tvrzení doplněním referencí na věrohodné zdroje.
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í potenciálně nebezpečných znaků.

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. Na internetu je však 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í.

Blind SQL injection
Blind SQL injection se používá, pokud je webová aplikace náchylná k SQL injection útoku, ale výsledek útoku se útočníkovi nezobrazí. Takto zranitelná stránka nemusí být jediná, která zobrazuje data, ale zobrazí se rozdílně v závislosti na výsledku logického výrazu vloženého do SQL dotazu na databázi. Tento typ útoku může být časově náročný, protože každý nový výraz musí být vytvořen pro každý odhalený bit. Existuje několik nástrojů, které pomohou automatizovat tyto útoky, jakmile byla zjištěna lokace zranitelnosti a cílová informace byla zjištěna.

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í autentizač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 by tedy útočník v předešlém příkladě jako jméno zadal:

a';DROP TABLE uzivatele; --
vypadal by dotaz při odeslání serveru jako:

statement := "SELECT * FROM uzivatele WHERE jmeno = 'a';DROP TABLE uzivatele; --';"
čímž by smazal celou tabulku uživatelů. Poslední apostrof se pomocí sekvence dvou pomlček stane poznámkou a nemá žádný 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.

Obrana na straně aplikace
Přímočarý, i když k chybám náchylný způsob, jak zabránit SQL útokům, je takzvané „Escapování“ znaků, které mají speciální význam v SQL. Manuál pro SQL DBMS vysvětluje, které znaky mají speciální význam, což povoluje vytvoření blacklistu znaků, které potřebují přeložit. Například každý výskyt uvozovky (') v parametru musí být nahrazen dvěma uvozovkami pro vytvoření úplného validního řetězce. Například v PHP je při escapování zvykem používat funkcí mysql_real_escape_string() ještě před odesláním dotazu na databázi.

Příklad v jazyce Perl
$query = $sql->prepare(
"SELECT * FROM uzivatele WHERE jmeno = "
. $sql->quote($zadaneJmeno)
);
Příklad v jazyce PHP (MySQL)
Knihovna MySQL, je nyní v jazyce PHP označena za zastaralou (bude v některé z následujících verzí jazyka PHP odstraněna).

$query = sprintf("SELECT * FROM `Users` WHERE UserName='%s' AND Password='%s'",
mysql_real_escape_string($Username),
mysql_real_escape_string($Password));
mysql_query($query);
Příklad v jazyce PHP (MySQLi)
Příklad využívá moderní knihovnu MySQLi:

$link = @mysqli_connect(db_hostname, db_username, db_password, db_name); //otevření nového připojení do MySQL

$val1 = mysqli_real_escape_string($link, $_POST["va1"]); //escapuje nedovolené znaky ze superglob. proměnné
$val2 = mysqli_real_escape_string($link, $_GET["va1"]); //escapuje nedovolené znaky ze superglob. proměnné

$query = sprintf("SELECT * FROM `test` WHERE value1='%s' AND value2='%s'",
$val1,
$val2); //vytvoří dotaz do databáze s již ošetřenými hodnotami

$result = mysqli_query($link, $query); //vrací výsledek dotazu
/*
Zde můžeme využívat výsledky z databáze uložené v $result např.:
while($row = mysqli_fetch_object($result)) {
echo $row->value3;
...
}
*/
mysqli_close($link); //uzavřeme spojení s databází
Takto může vypadat ošetřený kód proti sql injection. Vstupní proměnné jsou zde ošetřeny pomocí funkce mysqli_real_escape_string(mysqli $link, string $escapestr), která přidá zpětné lomítko následujícím znakům: \x00, \r, \n, \, ', , a \x1a. Tato funkce by měla být použita pro každou proměnnou předávanou dotazu. Ovšem existují i výjimky u kterých je zbytečné tuto funkci použit, např. pokud se jedná o proměnnou obsahující pouze celé číslo (int).

Příklad v jazyce PHP (Oracle)
$stmt = oci_parse($connOci, 'SELECT * FROM LOGIN WHERE jmeno = :login');
oci_bind_by_name($stmt, ':login', $_POST['login']);
oci_execute($stmt);
Existuje však mnoho funkcí pro různé typy databází v PHP, jako například pg_escape_string() for PostgreSQL. Další funkce, slouží k ochraně databází, které neobsahují funkce pro escapování v SQL. Funkce se nazývá addslashes(string $str). Navrací string se zpětnými lomítky před znaky, které musí v dotazech na databázi být v uvozovkách. Mezi tyto znaky patří jednoduchá uvozovka ('), dvojitá uvozovka (“), zpětné lomítko (\) a NULL. Běžné předávání escapovaných řetězců SQL databázi je náchylné k chybám, protože je snadné zapomenout daný řetězec escapovat. Vytvoření transparentní vrstvy k ošetření dat ze vstupu může snížit náchylnost k chybám, dokonce ji eliminovat úplně.

Obecně řečeno, spolu s tímto je vhodné aplikaci otestovat pro všechny možnosti uživatelského vstupu. Ve vývojové verzi se doporučuje mít nastavenu nízkou úroveň vypisování chybových hlášek a varování (abychom si jich všimnuli a opravili je). V ostré verzi je naopak zvykem vypisování chybových hlášek co nejvíc potlačit (mohly by poskytnout útočníkovi dodatečné informace).

Obrana 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. k čemuž je možné využít i tzv. VIEW (zúžený nebo naopak syntetizovaný pohled na tabulky v databázi). Málokdy je třeba přímo z aplikační vrstvy mazat tabulky či dokonce databáze, proto je možné omezit i dostupné SQL příkazy.

Případy SQL injection
1. listopadu 2006 použil jistý student SQL injection, aby pronikl na stránky tchajvanského časopisu o počítačové bezpečnosti.
29. června 2007 hacker „znetvořil“ stránku britské pobočky firmy Microsoft.[2] Její databázový systém se stal terčem útoku v lednu následujícího roku, kdy byl spuštěn hromadný útok zneužívající chyby v Microsoft SQL Server na SQL injection a byly nakaženy desítky tisíc počítačů, zejména v Číně. Další, ještě větší vlna útoků, zaměřující se na bezpečnostní díry Microsoft IIS a Microsoft SQL server, proběhla od dubna do srpna 2008 a odhadem zasáhla kolem půl milionu počítačů.
13. dubna 2008 vypnul registr sexuálních a násilných útočníků státu Oklahoma svoji webovou stránku z důvodu „údržby“ poté, co byl informován, že 10 579 čísel sociálního zabezpečení patřících útočníkům bylo staženo skrze SQL injection útok.
17. srpna 2009 obvinilo soudní oddělení spojených státu amerického občana Alberta Gonzalese a dva nejmenované Rusy za krádež 130 milionů čísel kreditních karet za pomoci SQL injection útoku. Údajně „největší krádež identity v dějinách Ameriky.“ Muž ukradl karty mnoha obětem útoku, poté co sledoval jejich platby. Mezi zasaženými společnostmi byl výrobce kreditních karet Heartland Payment Systems, obchodní řetězec s příslušenstvím 7-Eleven a řetězec supermarketů Hannaford Brothers.
V červenci 2010 jihoamerický výzkumník bezpečnosti spadající pod Ch Russo získal citlivé uživatelské informace z populární BitTorrent stránky The Pirate Bay. Získal přístup k hlavnímu panelu administrace a zneužil SQL injection zranitelnosti. Tím získal informace o uživatelských účtech, včetně IP adres, MD5 hesel a záznamy o uploadovaných torrentech.
24.–26. července 2010 hackeři z Japonska a Číny použili SQL injection, aby získali přístup k datům z kreditních karet zákazníků Neo Beat – společnosti se sídlem v Osace, která provozuje obrovskou síť internetových obchodů. Útok se netýkal pouze Neo Beat, ale i jejích sedmi obchodních partnerů včetně řetězců supermarketů Izumiya Co, Maruetsu Inc and Ryukyu Jusco Co. Krádež dat zaznamenalo 12 191 zákazníků. 14. srpna 2010 bylo nahlášeno přes 300 zneužití kreditních karet třetí stranou k objednání zboží a služeb v Číně.
8. listopadu 2010 byly napadeny stránky britského královského námořnictva za pomoci SQL injection.
27. března 2011 byla za pomoci SQL blind injection napadena domácí stránka MYSQL mysql.com. Za útokem stojí TinKode.
V srpnu 2011 ukradl hacker uživatelské záznamy z vývojářské stránky Nokia za pomoci SQL injection.
V září 2011 získali turečtí hackeři přístup k DNS záznamům NetNames a přesměrovali uživatele na vlastní stránku. Tento útok se týkal uživatelů Betfair (internetové sázení), The Telegraph, The Register, The National Geographic, UPS, Acer a Vodafone.com. K útoku se následně přiznali. Zveřejnili to na Zone-H.
Mezi (poměrně úzkou) komunitou programátorů, bezpečnostních analytiků a databázových návrhářů se v posledních několika měsících dokonce rozšířil humor, narážející na některé tyto útoky, mezi jinými i SQL injection.