Čo je to SQL injekcia?
SQL injekcie predstavujú významnú hrozbu pre relačné databázové modely a citlivé informácie, ktoré obsahujú. Preto je absolútne nevyhnutná komplexná ochrana proti týmto neoprávneným pokusom o externý prístup, ktoré sú možné vďaka bezpečnostným zraniteľnostiam.
Čo je SQL injekcia?
SQL injekcia je typ útoku, ktorý zneužíva bezpečnostnú chybu v relačných databázových systémoch, ktoré používajú jazyk SQL na spracovanie užívateľských vstupov. Útočník využíva užívateľské vstupy, ktoré nie sú správne escapované a obsahujú špeciálne znaky, ako sú dvojité pomlčky, úvodzovky alebo bodkočiarky. Tieto znaky majú špeciálne funkcie pre interpret SQL a umožňujú externú manipuláciu s vykonávanými príkazmi. SQL injekcie sú často spojené s aplikáciami PHP a ASP, ktoré sa spoliehajú na zastarané rozhrania. V mnohých z týchto prípadov nie je vstup dostatočne očistený, čo z neho robí hlavný cieľ útoku.
Strategickým vkladaním funkčných znakov môže neoprávnený používateľ vložiť ďalšie príkazy SQL a manipulovať so záznamami v databáze, aby mohol čítať, upravovať alebo mazať údaje. V závažných prípadoch môžu útočníci získať dokonca prístup k príkazovému riadku systému, čo im môže umožniť prevziať úplnú kontrolu nad databázovým serverom.
Príklad SQL injekcie ukazujúci, ako funguje útok na databázu
Vzhľadom na to, že zraniteľné databázové servery je možné rýchlo identifikovať a útoky typu SQL injection sú relatívne ľahko realizovateľné, táto metóda zostáva jednou z najčastejšie používaných techník medzi kyberzločincami po celom svete. Útočníci využívajú rôzne stratégie a zneužívajú tak novo objavené, ako aj dlhodobo existujúce bezpečnostné chyby v aplikáciách zapojených do procesu správy údajov. Aby sme lepšie pochopili, ako SQL injection funguje v praxi, pozrime sa na dva bežné spôsoby útoku ako príklady.
Príklad 1: Prístup prostredníctvom zle escapovaného používateľského vstupu
Na prístup do databázy sa od používateľov zvyčajne vyžaduje, aby sa najskôr overili. Na tento účel sa bežne používajú skripty, ktoré zobrazujú prihlasovací formulár s políčkami pre používateľské meno a heslo. Používatelia vyplnia formulár a skript potom skontroluje, či v databáze existujú zodpovedajúce záznamy. V predvolenom nastavení môže databáza obsahovať tabuľku s názvom users so stĺpcami username a password. V typickej webovej aplikácii môžu príslušné riadky skriptu pre prístup k databáze (používajúce pseudokód podobný jazyku Python) vyzerať takto:
uname = request.POST['username']
passwd = request.POST['password']
sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + passwd + "'"
database.execute(sql)pythonÚtočník môže teraz manipulovať s poľom hesla pomocou SQL injekcie, napríklad zadávaním password' OR 1='1, čo vedie k nasledujúcemu SQL dotazu:
sql = "SELECT id FROM users WHERE username='' AND password='password' OR 1='1'"pythonTýmto spôsobom získa útočník plný prístup k celej tabuľke používateľov v databáze, pretože podmienka hesla sa vždy vyhodnotí ako pravdivá (1='1'). Ak sa útočník prihlási ako správca, môže voľne upravovať akékoľvek záznamy v databáze. Alternatívne je možné rovnakým spôsobom manipulovať s poľom používateľského mena.
Príklad 2: Extrakcia údajov prostredníctvom manipulácie s ID
Vyhľadávanie informácií z databázy podľa ID je praktická a bežná metóda, ale zároveň otvára možnú bránu pre SQL injekciu. Napríklad webový server vie prostredníctvom prenesených údajov ID v URL, ktoré informácie má vyvolať z databázy. Príslušný skript PHP vyzerá takto:
<?php
$mysqli = new mysqli("localhost", "username", "password", "database");
$id = intval($_GET['id']);
$result = $mysqli->query("SELECT * FROM table WHERE id=$id");
while ($row = $result->fetch_assoc()) {
echo print_r($row, true);
}
?>phpOčakávaná URL adresa má vzor .../script.php?id=22. V tomto prípade by sa načítajú údaje z tabuľky s ID „22“. Ak má neoprávnená osoba možnosť manipulovať s touto URL adresou a namiesto toho pošle požiadavku ako .../script.php?id=22+OR+1=1, výsledný dotaz spôsobí načítanie všetkých riadkov v tabuľke:
SELECT * FROM table WHERE id=22 OR 1=1;sqlAko zločinci nájdu zraniteľné databázové systémy?
V zásade môže byť akákoľvek webová stránka alebo webová aplikácia, ktorá používa databázy SQL bez pripravených dotazov (pripravených príkazov) alebo iných ochranných opatrení, zraniteľná voči SQL injekciám. Objavené zraniteľnosti nezostávajú na World Wide Web dlho skryté. Existujú dokonca webové stránky, ktoré zverejňujú aktuálne zoznamy známych bezpečnostných chýb a dokonca vysvetľujú, ako môžu útočníci pomocou vyhľadávania Google nájsť zodpovedajúce webové projekty. Ak webová stránka vráti podrobné správy o chybách SQL, kyberzločinci môžu tieto správy využiť na identifikáciu potenciálnych zraniteľností. Napríklad pridanie apostrofu na koniec URL adresy, ktorá obsahuje parameter ID, môže už odhaliť slabinu, ako ukazuje nasledujúci príklad:
[DomainName].com/news.php?id=5’Zraniteľná webová stránka odošle späť chybovú správu v nasledujúcej forme:
Query failed: You have an error in your SQL syntax…
Podobné metódy možno použiť aj na získanie počtu stĺpcov, názvov tabuliek a stĺpcov, verzie SQL alebo dokonca používateľských mien a hesiel. Okrem toho existujú rôzne nástroje, ktoré môžu automatizovať proces vyhľadávania aj vykonávanie útokov typu SQL injection.
Ako chrániť svoju databázu pred SQL injekciou
Existuje viacero rôznych metód, ktoré môžete použiť na prevenciu útokov typu SQL injection na váš databázový systém. Mali by ste sa zaoberať všetkými zúčastnenými komponentmi – serverom a jednotlivými aplikáciami, ako aj systémom správy databázy.
Krok 1: Monitorujte automatické vstupy z aplikácií
Pri spracovaní vstupov z externých alebo integrovaných aplikácií je nevyhnutné overovať a filtrovať odoslané hodnoty, aby sa zabránilo SQL injekciám.
1. Overte typy údajov
Každý vstup by mal zodpovedať očakávanému typu údajov. Ak je napríklad vyžadovaný číselný vstup, jednoduchá validácia v PHP môže vyzerať takto:
if (filter_var($input, FILTER_VALIDATE_INT) === false) {
throw new InvalidArgumentException("Invalid input");
}phpPodobné kontroly by sa mali vykonávať aj pre reťazce, dátumy alebo iné špecifické formáty.
2. Filtrovanie špeciálnych znakov
Špeciálne znaky môžu vytvárať bezpečnostné chyby, najmä v kontexte SQL alebo HTML. Bezpečným prístupom je použiť htmlspecialchars() pre vstup HTML a PDO::quote() pre dotazy SQL.
3. Vyhnite sa zobrazovaniu chybových správ
Priame chybové správy, ktoré odhaľujú technické podrobnosti o databáze alebo systéme, by sa mali vyhnúť. Namiesto toho zobrazte všeobecnú správu, napríklad:
echo "An error occurred. Please try again later.";
error_log("Unexpected error encountered. See system log for details.");php4. Používajte pripravené vyhlásenia
Jedným z najúčinnejších spôsobov, ako zabrániť SQL injekciám, je použitie pripravených príkazov. Pri tomto prístupe sa SQL príkazy a parametre odosielajú samostatne, takže sa nemôže spustiť škodlivý kód. Tu je príklad implementácie v PHP pomocou PDO (PHP Data Objects):
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(':id', $user_id, PDO::PARAM_INT);
$stmt->execute();phpSystém správy databázy automaticky zabezpečuje, že vstupné údaje sú spracované bezpečne.
Krok 2: Zabezpečte komplexnú ochranu servera
Bezpečnosť servera, na ktorom beží váš systém správy databáz, tiež zohráva kľúčovú úlohu v prevencii SQL injekcií. Kľúčovým opatrením je posilnenie operačného systému dodržiavaním týchto osvedčených postupov:
- Nainštalujte alebo aktivujte iba aplikácie a služby, ktoré sú nevyhnutné pre prevádzku databázy.
- Odstráňte všetky nepoužívané alebo nepotrebné používateľské účty.
- Zabezpečte, aby boli všetky relevantné aktualizácie systému a softvéru nainštalované bezodkladne.
- Uplatňujte zásadu minimálnych oprávnení, aby ste zaistili, že používatelia a služby majú len minimálne potrebné oprávnenia.
V závislosti od bezpečnostných požiadaviek vášho webového projektu by ste mali zvážiť ďalšie ochranné opatrenia:
- Systémy detekcie narušenia (IDS) a systémy prevencie narušenia (IPS): Tieto systémy používajú rôzne metódy detekcie na včasnú identifikáciu útokov, vydávanie varovaní a – pri použití IPS – automatické spustenie protiopatrení.
- Brána aplikačnej vrstvy (ALG): ALG monitoruje a filtruje prevádzku medzi aplikáciami a webovými prehliadačmi priamo na úrovni aplikácií.
- Web Application Firewall (WAF): WAF špecificky chráni webové aplikácie pred SQL injekciami a Cross-Site Scripting (XSS) blokovaním alebo čistením podozrivých požiadaviek.
- Prístup Zero Trust: Tento moderný bezpečnostný model zabezpečuje, že každý pokus o prístup – bez ohľadu na jeho pôvod – je overený a autentizovaný pred udelením prístupu.
- Pravidlá brány firewall a segmentácia siete: Tieto sú nevyhnutné na dlhodobé minimalizovanie plochy útoku.
- Pravidelné audity IT bezpečnosti a penetračné testy: Pomáhajú odhaliť a opraviť zraniteľnosti v ranom štádiu.
Krok 3: Zabezpečte databázu a používajte bezpečný kód
Rovnako ako operačný systém, aj databáza by mala byť zbavená všetkých nepotrebných komponentov a udržiavaná v aktuálnom stave. Odstráňte všetky uložené procedúry, ktoré nepotrebujete, a deaktivujte všetky nepoužívané služby a používateľské účty. Vytvorte vyhradený databázový účet určený výlučne pre webový prístup a priraďte mu len minimálne požadované oprávnenia.
V súlade s používaním pripravených príkazov sa dôrazne odporúča nepoužívať modul mysql PHP (ktorý bol v PHP 7 odstránený). Namiesto toho zvoľte mysqli alebo PDO, aby ste zaistili lepšiu bezpečnosť a kompatibilitu. Bezpečný mysqli dotaz môže vyzerať takto:
$mysqli = new mysqli("localhost", "username", "password", "database");
if ($mysqli->connect_error) die("Connection failed");
$stmt = $mysqli->prepare("SELECT password FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$stmt->bind_result($hashedPassword);
if ($stmt->fetch() && password_verify($_POST['password'], $hashedPassword)) {
echo "Login successful";
} else {
echo "Invalid login credentials";
}
$stmt->close();
$mysqli->close();phpHeslá by sa nikdy nemali ukladať priamo do databázy ani sa nemali získavať v podobe obyčajného textu. Namiesto toho použite metódu hashovania, ako je password_hash(), v kombinácii s password_verify(), aby ste bezpečne chránili prihlasovacie údaje. Bezpečná implementácia môže vyzerať takto:
$mysqli = new mysqli("localhost", "username", "password", "database");
$stmt = $mysqli->prepare("SELECT password FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
if ($row && password_verify($_POST['password'], $row['password'])) {
echo "Login successful!";
} else {
echo "Incorrect username or password.";
}phpČo majú bobby tabuľky spoločné s SQL injekciou?
Webová stránka bobby-tables.com používa webový komiks xkcd, aby humorne ilustrovala nebezpečenstvo nezabezpečených užívateľských vstupov do databáz. V komikse matka dostane telefonát zo školy svojho syna (známy pod prezývkou Little Bobby Tables). Volajúci sa opýta, či sa jej syn naozaj volá Robert'); DROP TABLE Students;--, na čo ona odpovie áno. Dôvod telefonátu sa čoskoro vyjasní: pokus o zadanie mena Robert do databázy žiakov spôsobil vymazanie celej tabuľky žiakov. Matka nie je príliš súcitná – jednoducho dúfa, že škola si vzala ponaučenie a v budúcnosti bude vstupy do databázy dezinfikovať.
Komiks jasne poukazuje na katastrofické dôsledky, ktoré môžu nastať v dôsledku nesprávnej validácie a sanitizácie užívateľských vstupov v databázových aplikáciách.