SQL-süstid kujutavad endast suurt ohtu re­lat­sioo­ni­lis­tele and­me­baasi­mu­de­li­tele ja nendes si­sal­du­vale tund­li­kule teabele. Seetõttu on hä­da­va­ja­lik tagada põhjalik kaitse selliste vo­li­ta­mata väliste juur­de­pää­su­katse vastu, mis on või­ma­li­kud tur­va­au­kude tõttu.

Mis on SQL-süst?

SQL-süst on rün­na­ku­tüüp, mis kasutab ära turvaauku re­lat­sioo­ni­lis­tes and­me­baasi­süs­teemi­des, mis töötlevad kasutaja sisestusi SQL-pä­rin­gu­keele abil. Ründaja kasutab ära kasutaja sisestusi, mis ei ole nõue­te­ko­ha­selt pu­has­ta­tud ja si­sal­da­vad erimärke, nagu to­pelt­kriip­sud, ju­tu­mär­gid või se­mi­koo­lo­nid. Nendel märkidel on SQL-tõlke jaoks eri­funkt­sioo­nid ning need või­mal­da­vad väliselt ma­ni­pu­lee­rida täi­de­ta­vaid käske. SQL-in­jekt­sioone seos­ta­takse sageli PHP- ja ASP-ra­ken­dus­tega, mis tuginevad vananenud lii­des­tele. Paljudel juhtudel ei ole sisestusi piisavalt pu­has­ta­tud, mistõttu on need rünnakute peamine sihtmärk.

Funkt­sioo­ni­mär­kide stra­tee­gi­lise si­ses­ta­mise abil võib vo­li­ta­mata kasutaja lisada täien­da­vaid SQL-käsklusi ja ma­ni­pu­lee­rida and­me­ba­asi kirjetega, et andmeid lugeda, muuta või kustutada. Ras­ke­ma­tel juhtudel võivad ründajad saada juur­de­pääsu isegi süsteemi käsureale, mis võib või­mal­dada neil võtta and­me­ba­asi serveri täie­li­kult oma kontrolli alla.

SQL-süstimise näide, mis il­lust­ree­rib and­me­ba­asi ründe toimimist

Kuna haa­va­ta­vaid and­me­baasi­ser­ve­rid on võimalik kiiresti tuvastada ja SQL-süs­ti­mis­rün­na­kuid on suh­te­li­selt lihtne teostada, on see meetod endiselt üks kü­ber­kur­ja­te­gi­jate seas kogu maailmas enim ka­su­ta­ta­vaid tehnikaid. Ründajad kasutavad erinevaid stra­tee­giaid, ära­ka­su­ta­des nii äsja avastatud kui ka juba ammu tea­daole­vaid turvaauke and­me­hal­dus­prot­ses­sis osale­va­tes ra­ken­dus­tes. Et paremini mõista, kuidas SQL-süstimine praktikas toimib, vaatame näidetena kahte levinud rün­na­ku­mee­to­dit.

Näide 1: Juur­de­pääs halvasti pu­has­ta­tud kasutaja sisestuse kaudu

And­me­baasile juur­de­pääs­uks peavad kasutajad ta­va­li­selt esmalt end autentima. Selleks ka­su­ta­takse sageli skripte, mis kuvavad sis­se­lo­gi­mis­vormi, kus on ka­su­ta­ja­nime ja parooli väljad. Kasutajad täidavad vormi ja skript kont­rol­lib seejärel, kas and­me­baasis on vastavaid kirjeid. Vaikimisi võib andmebaas sisaldada tabelit nimega users, millel on veerud username ja password. Tüü­pi­li­ses vee­bi­ra­ken­duses võivad and­me­baasile juur­de­pääsu jaoks vajalikud skripti read (kasutades Python-laadset pseu­do­koodi) välja näha järg­mi­selt:

uname = request.POST['username']
passwd = request.POST['password']
sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + passwd + "'"
database.execute(sql)
python

Ründaja saab nüüd SQL-süsti abil pa­roo­li­välja ma­ni­pu­lee­rida, näiteks si­ses­ta­des 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'"
python

See annab ründajale täieliku juur­de­pääsu and­me­ba­asi kogu ka­su­ta­jate tabelile, kuna pa­roo­li­tin­gi­mus annab alati tu­le­mu­seks „tõene“ (1='1'). Kui ründaja logib sisse ad­mi­nist­raa­to­rina, saab ta vabalt muuta kõiki and­me­ba­asi kirjeid. Samamoodi on võimalik ma­ni­pu­lee­rida ka ka­su­ta­ja­nime väljaga.

Näide 2: Andmete väl­ja­võt­mine ID-de muutmise teel

Andmete päring and­me­baasist ID järgi on prak­ti­line ja levinud meetod, kuid see avab ka võimaluse SQL-süs­ti­miseks. Näiteks teab vee­bi­ser­ver URL-is edastatud ID andmete põhjal, millised andmed ta and­me­baasist 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);
    }
?>
php

Oodatav URL järgib mustrit .../script.php?id=22. Sel juhul kuvataks tabeli kirje ID-ga „22”. Kui vo­li­ta­mata 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;
sql

Kuidas kur­ja­te­gi­jad leiavad haa­va­ta­vaid and­me­baasi­süs­teeme?

Põ­hi­mõt­te­li­selt võib iga veebisait või vee­bi­ra­ken­dus, mis kasutab SQL-and­me­baase ilma et­te­val­mis­ta­tud pä­rin­gu­teta (prepared sta­te­ments) või muude kait­se­meet­me­teta, olla haavatav SQL-süstide suhtes. Avastatud tur­va­au­gud ei jää veebis kauaks varjatuks. Te­ge­li­kult on olemas vee­bi­saite, mis avaldavad aja­ko­ha­seid nimekirju tea­daole­va­test tur­va­prob­leemi­dest – ja sel­gi­ta­vad isegi, kuidas ründajad saavad Google’i otsingute abil leida sobivaid vee­bi­pro­jekte. Kui veebisait kuvab ük­sik­as­ja­likke SQL-vea­tea­teid, saavad kü­ber­kur­ja­te­gi­jad neid kasutada po­tent­siaal­sete haa­va­ta­vuste tu­vas­ta­miseks. Näiteks võib ID-pa­ra­meet­rit sisaldava URL-i lõppu apost­roofi lisamine juba pal­jas­tada 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 ka­su­ta­ja­ni­mede ja paroolide väl­ja­sel­gi­ta­miseks. Lisaks on olemas mit­me­su­gu­seid tööriistu, millega saab au­to­ma­ti­see­rida nii andmete väl­ja­sel­gi­ta­mise protsessi kui ka SQL-süs­ti­mis­rün­na­kute lä­bi­vii­mise.

Kuidas kaitsta oma and­me­ba­asi SQL-süstide eest

And­me­baasi­süs­teemi SQL-süs­ti­mis­rün­na­kute ära­hoid­miseks on olemas mit­me­su­gu­seid meetodeid. Tuleb tegeleda kõigi as­ja­omaste kom­po­nen­ti­dega – nii serveri ja üksikute ra­ken­duste kui ka and­me­ba­asi hal­dus­süs­tee­miga.

1. samm: Ra­ken­dus­test tulevate au­to­maat­sete si­ses­tuste jälgimine

Välistest või sis­se­ehi­ta­tud ra­ken­dus­test saadud sisendite tööt­le­misel on SQL-süstide väl­ti­miseks hä­da­va­ja­lik esitatud väärtusi kont­rol­lida ja filt­ree­rida.

1. And­me­tüü­pide kont­rol­li­mine

Iga sisend peab vastama ooda­ta­vale and­me­tüü­bile. Näiteks kui nõutakse numb­ri­list sisendit, võiks lihtne va­li­dee­ri­mine PHP-s välja näha järgmine:

if (filter_var($input, FILTER_VALIDATE_INT) === false) {
    throw new InvalidArgumentException("Invalid input");
}
php

Sarnaseid kontrolle tuleks rakendada ka stringide, kuu­päe­vade või muude spet­sii­fi­liste vor­min­gute puhul.

2. Eri­mär­kide filt­ree­ri­mine

Erimärgid võivad tekitada turvaauke, eriti SQL- või HTML-kon­teks­tis. Turvaline lä­he­ne­mis­viis on kasutada HTML-sisestuse puhul htmlspecialchars() ja SQL-päringute puhul PDO::quote().

3. Vältige vea­tea­dete kuvamist

Tuleks vältida otseseid vea­tea­teid, mis pal­jas­ta­vad and­me­ba­asi 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.");
php

4. Kasutage eel­val­mis­ta­tud päringuid

Üks tõ­hu­samaid viise SQL-süstide väl­ti­miseks on val­mis­laa­di­tud päringute ka­su­ta­mine. Selle meetodi puhul saa­de­takse SQL-käskud ja pa­ra­meet­rid eraldi, mistõttu pa­ha­taht­likku koodi ei ole võimalik käivitada. Siin on näide ra­ken­da­mi­sest 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();
php

And­me­ba­asi hal­dus­süs­teem tagab au­to­maat­selt, et si­ses­ta­tud andmed töö­del­dakse tur­va­li­selt.

2. samm: Tagage serveri igakülgne kaitse

SQL-süstide en­ne­ta­misel on oluline roll ka selle serveri tur­va­li­su­sel, kus teie and­me­baasi­hal­dus­süs­teem töötab. Üks peamisi meetmeid on ope­rat­sioo­ni­süs­teemi tur­va­li­suse tu­gev­da­mine, järgides järgmisi parimaid tavasid:

  • Pai­gal­dage või ak­ti­vee­rige ainult need ra­ken­dused ja teenused, mis on and­me­ba­asi töö­ta­miseks hä­da­va­ja­li­kud.
  • Kustutage kõik ka­su­ta­mata või mit­te­va­ja­li­kud ka­su­ta­ja­kon­tod.
  • Veenduge, et kõik as­ja­ko­ha­sed süsteemi- ja tark­va­rauuen­dused pai­gal­da­takse vii­vi­ta­ma­tult.
  • Rakendage mi­ni­maalse õiguse põhimõtet, et tagada, et ka­su­ta­ja­tele ja tee­nus­tele antakse ainult mi­ni­maal­sed vajalikud õigused.

Sõltuvalt vee­bi­pro­jekti tur­va­nõue­test peaksite kaaluma täien­da­vate kait­se­meet­mete ra­ken­da­mist:

  • Sis­se­tun­gi­jate tu­vas­ta­mise süsteemid (IDS) ja sis­se­tun­gi­jate tõ­kes­ta­mise süsteemid (IPS): Need süsteemid kasutavad erinevaid tu­vas­tus­mee­to­deid, et rünnakuid varakult avastada, hoiatusi edastada ja – IPS-i ka­su­ta­misel – au­to­maat­selt vas­tu­meet­meid rakendada.
  • Ra­ken­dus­kihi värav (ALG): ALG jälgib ja filt­ree­rib liiklust ra­ken­duste ja vee­bib­rau­se­rite vahel otse ra­ken­duste tasandil.
  • Vee­bi­ra­ken­duste tulemüür (WAF): WAF kaitseb vee­bi­ra­ken­dusi spet­siaal­selt SQL-süstide ja rist­vee­bisk­rip­ti­mise (XSS) eest, blo­kee­ri­des või pu­has­ta­des kahtlased päringud.
  • Zero Trust lä­he­ne­mine: see kaasaegne tur­va­li­sus­mu­del tagab, et iga juur­de­pää­su­katse – olenemata selle pä­rito­lust – kont­rol­li­takse ja au­ten­ti­takse enne juur­de­pääsu lubamist.
  • Tulemüüri reeglid ja võrgu seg­men­tat­sioon: need on olulised rün­na­ku­pinna pi­ka­aja­li­seks mini­mee­ri­miseks.
  • Re­gu­laar­sed IT-tur­beau­di­tid ja sis­se­tun­gi­tes­tid: need aitavad avastada ja parandada haa­va­ta­vusi varases staa­diu­mis.

3. samm: And­me­ba­asi tur­va­li­se­maks muutmine ja turvalise koodi ka­su­ta­mine

Nii nagu ope­rat­sioo­ni­süs­teem, peaks ka andmebaas olema va­bas­ta­tud kõigist mit­te­va­ja­li­kest kom­po­nen­ti­dest ja aja­ko­h­asena hoitud. Kustutage kõik mit­te­va­ja­li­kud sal­ves­ta­tud prot­se­duu­rid ning lülitage välja kõik ka­su­ta­mata teenused ja ka­su­ta­ja­kon­tod. Looge spet­siaalne and­me­ba­asi konto, mis on mõeldud ainult vee­bi­põ­hi­seks juur­de­pääs­uks, ning määrake sellele vaid mi­ni­maal­sed vajalikud õigused.

Val­mis­kü­si­muste ka­su­ta­mi­sega kooskõlas soo­vi­ta­takse tungivalt mitte kasutada mysql PHP-moodulit (mis eemaldati PHP 7-st). Valige selle asemel mysqli või PDO, et tagada parem tur­va­li­sus 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();
php

Paroolid ei tohi kunagi sal­ves­tada otse and­me­ba­asi ega edastada ta­va­teks­tina. Kasutage selle asemel paroolide tur­va­li­seks kaits­miseks 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.";
}
php

Mis seos on bobby-laudadel SQL-süs­ti­mi­sega?

Veebisait bobby-tables.com kasutab xkcd-vee­bi­koo­mik­sit, et il­lust­ree­rida hu­moo­ri­kalt and­me­baasi­des eba­tur­va­lise ka­su­ta­ja­si­ses­tuse ohtusid. Koomiksis saab ema kõne oma poja (keda hel­li­ta­valt kut­su­takse 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 and­me­ba­asi põhjustas kogu õpilaste tabeli kus­tu­ta­mise. Ema ei ole eriti kaas­tund­lik – ta loodab lihtsalt, et kool on õppinud oma õppetundi ja puhastab edaspidi and­me­ba­asi sisestusi.

Koomiks toob selgelt esile ka­tast­roo­fi­li­sed ta­ga­jär­jed, mis võivad tekkida, kui and­me­baasi­ra­ken­dus­tes ei kont­rol­lita ega puhastata kasutaja si­ses­ta­tud andmeid nõue­te­ko­ha­selt.

Go to Main Menu