Mis on SQL-süst?
SQL-süstid kujutavad endast suurt ohtu relatsioonilistele andmebaasimudelitele ja nendes sisalduvale tundlikule teabele. Seetõttu on hädavajalik tagada põhjalik kaitse selliste volitamata väliste juurdepääsukatse vastu, mis on võimalikud turvaaukude tõttu.
Mis on SQL-süst?
SQL-süst on rünnakutüüp, mis kasutab ära turvaauku relatsioonilistes andmebaasisüsteemides, mis töötlevad kasutaja sisestusi SQL-päringukeele abil. Ründaja kasutab ära kasutaja sisestusi, mis ei ole nõuetekohaselt puhastatud ja sisaldavad erimärke, nagu topeltkriipsud, jutumärgid või semikoolonid. Nendel märkidel on SQL-tõlke jaoks erifunktsioonid ning need võimaldavad väliselt manipuleerida täidetavaid käske. SQL-injektsioone seostatakse sageli PHP- ja ASP-rakendustega, mis tuginevad vananenud liidestele. Paljudel juhtudel ei ole sisestusi piisavalt puhastatud, mistõttu on need rünnakute peamine sihtmärk.
Funktsioonimärkide strateegilise sisestamise abil võib volitamata kasutaja lisada täiendavaid SQL-käsklusi ja manipuleerida andmebaasi kirjetega, et andmeid lugeda, muuta või kustutada. Raskematel juhtudel võivad ründajad saada juurdepääsu isegi süsteemi käsureale, mis võib võimaldada neil võtta andmebaasi serveri täielikult oma kontrolli alla.
SQL-süstimise näide, mis illustreerib andmebaasi ründe toimimist
Kuna haavatavaid andmebaasiserverid on võimalik kiiresti tuvastada ja SQL-süstimisrünnakuid on suhteliselt lihtne teostada, on see meetod endiselt üks küberkurjategijate seas kogu maailmas enim kasutatavaid tehnikaid. Ründajad kasutavad erinevaid strateegiaid, ärakasutades nii äsja avastatud kui ka juba ammu teadaolevaid turvaauke andmehaldusprotsessis osalevates rakendustes. Et paremini mõista, kuidas SQL-süstimine praktikas toimib, vaatame näidetena kahte levinud rünnakumeetodit.
Näide 1: Juurdepääs halvasti puhastatud kasutaja sisestuse kaudu
Andmebaasile juurdepääsuks peavad kasutajad tavaliselt esmalt end autentima. Selleks kasutatakse sageli skripte, mis kuvavad sisselogimisvormi, kus on kasutajanime ja parooli väljad. Kasutajad täidavad vormi ja skript kontrollib seejärel, kas andmebaasis on vastavaid kirjeid. Vaikimisi võib andmebaas sisaldada tabelit nimega users, millel on veerud username ja password. Tüüpilises veebirakenduses võivad andmebaasile juurdepääsu jaoks vajalikud skripti read (kasutades Python-laadset pseudokoodi) välja näha järgmiselt:
uname = request.POST['username']
passwd = request.POST['password']
sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + passwd + "'"
database.execute(sql)pythonRündaja saab nüüd SQL-süsti abil paroolivälja manipuleerida, näiteks sisestades sinna password' OR 1='1, mis tekitab järgmise SQL-päringu:
sql = "SELECT id FROM users WHERE username='' AND password='password' OR 1='1'"pythonSee annab ründajale täieliku juurdepääsu andmebaasi kogu kasutajate tabelile, kuna paroolitingimus annab alati tulemuseks „tõene“ (1='1'). Kui ründaja logib sisse administraatorina, saab ta vabalt muuta kõiki andmebaasi kirjeid. Samamoodi on võimalik manipuleerida ka kasutajanime väljaga.
Näide 2: Andmete väljavõtmine ID-de muutmise teel
Andmete päring andmebaasist ID järgi on praktiline ja levinud meetod, kuid see avab ka võimaluse SQL-süstimiseks. Näiteks teab veebiserver URL-is edastatud ID andmete põhjal, millised andmed ta andmebaasist välja peab otsima. Vastav PHP-skript näeb välja järgmine:
<?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);
}
?>phpOodatav URL järgib mustrit .../script.php?id=22. Sel juhul kuvataks tabeli kirje ID-ga „22”. Kui volitamata isikul on võimalus seda URL-i muuta ja ta saadab selle asemel päringu nagu .../script.php?id=22+OR+1=1, põhjustab see päring tabeli kõigi ridade kuvamise:
SELECT * FROM table WHERE id=22 OR 1=1;sqlKuidas kurjategijad leiavad haavatavaid andmebaasisüsteeme?
Põhimõtteliselt võib iga veebisait või veebirakendus, mis kasutab SQL-andmebaase ilma ettevalmistatud päringuteta (prepared statements) või muude kaitsemeetmeteta, olla haavatav SQL-süstide suhtes. Avastatud turvaaugud ei jää veebis kauaks varjatuks. Tegelikult on olemas veebisaite, mis avaldavad ajakohaseid nimekirju teadaolevatest turvaprobleemidest – ja selgitavad isegi, kuidas ründajad saavad Google’i otsingute abil leida sobivaid veebiprojekte. Kui veebisait kuvab üksikasjalikke SQL-veateateid, saavad küberkurjategijad neid kasutada potentsiaalsete haavatavuste tuvastamiseks. Näiteks võib ID-parameetrit sisaldava URL-i lõppu apostroofi lisamine juba paljastada nõrkuse, nagu on näidatud järgmises näites:
[DomainName].com/news.php?id=5’Haavatav veebisait saadab tagasi järgmise vormis veateate:
Query failed: You have an error in your SQL syntax…
Sarnaseid meetodeid saab kasutada ka veergude arvu, tabelite ja veergude nimede, SQL-versiooni või isegi kasutajanimede ja paroolide väljaselgitamiseks. Lisaks on olemas mitmesuguseid tööriistu, millega saab automatiseerida nii andmete väljaselgitamise protsessi kui ka SQL-süstimisrünnakute läbiviimise.
Kuidas kaitsta oma andmebaasi SQL-süstide eest
Andmebaasisüsteemi SQL-süstimisrünnakute ärahoidmiseks on olemas mitmesuguseid meetodeid. Tuleb tegeleda kõigi asjaomaste komponentidega – nii serveri ja üksikute rakenduste kui ka andmebaasi haldussüsteemiga.
1. samm: Rakendustest tulevate automaatsete sisestuste jälgimine
Välistest või sisseehitatud rakendustest saadud sisendite töötlemisel on SQL-süstide vältimiseks hädavajalik esitatud väärtusi kontrollida ja filtreerida.
1. Andmetüüpide kontrollimine
Iga sisend peab vastama oodatavale andmetüübile. Näiteks kui nõutakse numbrilist sisendit, võiks lihtne valideerimine PHP-s välja näha järgmine:
if (filter_var($input, FILTER_VALIDATE_INT) === false) {
throw new InvalidArgumentException("Invalid input");
}phpSarnaseid kontrolle tuleks rakendada ka stringide, kuupäevade või muude spetsiifiliste vormingute puhul.
2. Erimärkide filtreerimine
Erimärgid võivad tekitada turvaauke, eriti SQL- või HTML-kontekstis. Turvaline lähenemisviis on kasutada HTML-sisestuse puhul htmlspecialchars() ja SQL-päringute puhul PDO::quote().
3. Vältige veateadete kuvamist
Tuleks vältida otseseid veateateid, mis paljastavad andmebaasi või süsteemi tehnilisi üksikasju. Selle asemel tuleks kuvada üldine teade, näiteks:
echo "An error occurred. Please try again later.";
error_log("Unexpected error encountered. See system log for details.");php4. Kasutage eelvalmistatud päringuid
Üks tõhusamaid viise SQL-süstide vältimiseks on valmislaaditud päringute kasutamine. Selle meetodi puhul saadetakse SQL-käskud ja parameetrid eraldi, mistõttu pahatahtlikku koodi ei ole võimalik käivitada. Siin on näide rakendamisest PHP-s, kasutades PDO-d (PHP Data Objects):
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(':id', $user_id, PDO::PARAM_INT);
$stmt->execute();phpAndmebaasi haldussüsteem tagab automaatselt, et sisestatud andmed töödeldakse turvaliselt.
2. samm: Tagage serveri igakülgne kaitse
SQL-süstide ennetamisel on oluline roll ka selle serveri turvalisusel, kus teie andmebaasihaldussüsteem töötab. Üks peamisi meetmeid on operatsioonisüsteemi turvalisuse tugevdamine, järgides järgmisi parimaid tavasid:
- Paigaldage või aktiveerige ainult need rakendused ja teenused, mis on andmebaasi töötamiseks hädavajalikud.
- Kustutage kõik kasutamata või mittevajalikud kasutajakontod.
- Veenduge, et kõik asjakohased süsteemi- ja tarkvarauuendused paigaldatakse viivitamatult.
- Rakendage minimaalse õiguse põhimõtet, et tagada, et kasutajatele ja teenustele antakse ainult minimaalsed vajalikud õigused.
Sõltuvalt veebiprojekti turvanõuetest peaksite kaaluma täiendavate kaitsemeetmete rakendamist:
- Sissetungijate tuvastamise süsteemid (IDS) ja sissetungijate tõkestamise süsteemid (IPS): Need süsteemid kasutavad erinevaid tuvastusmeetodeid, et rünnakuid varakult avastada, hoiatusi edastada ja – IPS-i kasutamisel – automaatselt vastumeetmeid rakendada.
- Rakenduskihi värav (ALG): ALG jälgib ja filtreerib liiklust rakenduste ja veebibrauserite vahel otse rakenduste tasandil.
- Veebirakenduste tulemüür (WAF): WAF kaitseb veebirakendusi spetsiaalselt SQL-süstide ja ristveebiskriptimise (XSS) eest, blokeerides või puhastades kahtlased päringud.
- Zero Trust lähenemine: see kaasaegne turvalisusmudel tagab, et iga juurdepääsukatse – olenemata selle päritolust – kontrollitakse ja autentitakse enne juurdepääsu lubamist.
- Tulemüüri reeglid ja võrgu segmentatsioon: need on olulised rünnakupinna pikaajaliseks minimeerimiseks.
- Regulaarsed IT-turbeauditid ja sissetungitestid: need aitavad avastada ja parandada haavatavusi varases staadiumis.
3. samm: Andmebaasi turvalisemaks muutmine ja turvalise koodi kasutamine
Nii nagu operatsioonisüsteem, peaks ka andmebaas olema vabastatud kõigist mittevajalikest komponentidest ja ajakohasena hoitud. Kustutage kõik mittevajalikud salvestatud protseduurid ning lülitage välja kõik kasutamata teenused ja kasutajakontod. Looge spetsiaalne andmebaasi konto, mis on mõeldud ainult veebipõhiseks juurdepääsuks, ning määrake sellele vaid minimaalsed vajalikud õigused.
Valmisküsimuste kasutamisega kooskõlas soovitatakse tungivalt mitte kasutada mysql PHP-moodulit (mis eemaldati PHP 7-st). Valige selle asemel mysqli või PDO, et tagada parem turvalisus ja ühilduvus. Turvaline mysqli päring võiks välja näha järgmine:
$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();phpParoolid ei tohi kunagi salvestada otse andmebaasi ega edastada tavatekstina. Kasutage selle asemel paroolide turvaliseks kaitsmiseks hash-meetodit, näiteks password_hash() koos password_verify(). Turvaline rakendus võiks välja näha järgmine:
$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.";
}phpMis seos on bobby-laudadel SQL-süstimisega?
Veebisait bobby-tables.com kasutab xkcd-veebikoomiksit, et illustreerida humoorikalt andmebaasides ebaturvalise kasutajasisestuse ohtusid. Koomiksis saab ema kõne oma poja (keda hellitavalt kutsutakse Little Bobby Tablesiks) koolist. Helistaja küsib, kas poja nimi on tõesti Robert'); DROP TABLE Students;--, millele ema vastab jaatavalt. Kõne põhjus selgub peagi: katse sisestada Robert õpilaste andmebaasi põhjustas kogu õpilaste tabeli kustutamise. Ema ei ole eriti kaastundlik – ta loodab lihtsalt, et kool on õppinud oma õppetundi ja puhastab edaspidi andmebaasi sisestusi.
Koomiks toob selgelt esile katastroofilised tagajärjed, mis võivad tekkida, kui andmebaasirakendustes ei kontrollita ega puhastata kasutaja sisestatud andmeid nõuetekohaselt.