Kas yra SQL įterpimas?
SQL įterpimai kelia didelę grėsmę reliacinėms duomenų bazėms ir jose saugomai konfidencialiai informacijai. Būtent todėl būtina užtikrinti visapusišką apsaugą nuo šių neteisėtų išorinių prieigos bandymų, kuriuos leidžia saugumo pažeidžiamumai.
Kas yra SQL įterpimas?
SQL įterpimas – tai atakos rūšis, kuria pasinaudojama siekiant išnaudoti saugumo spragą reliacinėse duomenų bazių sistemose, kurios naudoja SQL užklausų kalbą vartotojo įvestims apdoroti. Puolėjas pasinaudoja vartotojo įvestimis, kurios nėra tinkamai apsaugotos ir kuriose yra specialių simbolių, pvz., dvigubų brūkšnelių, kabučių ar kabliataškių. Šie simboliai turi specialias funkcijas SQL interpretatoriui ir leidžia išoriškai manipuliuoti vykdomomis komandomis. SQL injekcijos dažnai siejamos su PHP ir ASP programomis, kurios naudoja pasenusias sąsajas. Daugeliu šių atvejų įvestis nėra tinkamai išvalyta, todėl tampa pagrindiniu atakos taikiniu.
Strategiškai įterpdamas funkcinius simbolius, neteisėtas vartotojas gali įterpti papildomas SQL komandas ir manipuliuoti duomenų bazės įrašais, kad galėtų skaityti, keisti ar trinti duomenis. Sunkiausiais atvejais užpuolikai gali netgi gauti prieigą prie sistemos komandų eilutės, o tai jiems gali leisti visiškai perimti duomenų bazės serverio kontrolę.
SQL įterpimo pavyzdys, iliustruojantis, kaip vyksta duomenų bazės ataka
Kadangi pažeidžiamus duomenų bazių serverius galima greitai nustatyti, o SQL įterpimo atakas vykdyti palyginti lengva, šis metodas vis dar yra vienas iš plačiausiai naudojamų būdų tarp kibernetinių nusikaltėlių visame pasaulyje. Piktadariai taiko įvairias strategijas, pasinaudodami tiek naujai atrastomis, tiek seniai žinomomis saugumo spragomis programose, naudojamose duomenų tvarkymo procese. Norėdami geriau suprasti, kaip SQL įterpimas veikia praktikoje, panagrinėkime du dažniausiai pasitaikančius atakos metodus kaip pavyzdžius.
1 pavyzdys: prieiga per netinkamai apdorotą vartotojo įvestį
Norėdami prisijungti prie duomenų bazės, vartotojai paprastai turi pirmiausia patvirtinti savo tapatybę. Šiam tikslui dažniausiai naudojami skriptai, kurie rodo prisijungimo formą su laukeliais vartotojo vardui ir slaptažodžiui įvesti. Vartotojai užpildo formą, o skriptas patikrina, ar duomenų bazėje yra atitinkamų įrašų. Pagal numatytuosius nustatymus duomenų bazėje gali būti lentelė pavadinimu users su stulpeliais username ir password. Tipinėje žiniatinklio programoje atitinkamos skripto eilutės, skirtos prisijungimui prie duomenų bazės (naudojant Python tipo pseudokodą), gali atrodyti taip:
uname = request.POST['username']
passwd = request.POST['password']
sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + passwd + "'"
database.execute(sql)pythonDabar įsilaužėlis gali manipuliuoti slaptažodžio laukeliu naudodamas SQL įterpimą, pavyzdžiui, įvedęs password' OR 1='1, dėl ko susidaro tokia SQL užklausa:
sql = "SELECT id FROM users WHERE username='' AND password='password' OR 1='1'"pythonTai suteikia įsilaužėliui visišką prieigą prie visos vartotojų lentelės duomenų bazėje, nes slaptažodžio sąlyga visada įvertinama kaip teisinga (1='1'). Jei įsilaužėlis prisijungs kaip administratorius, jis galės laisvai keisti bet kurį duomenų bazės įrašą. Be to, vartotojo vardo lauką galima manipuliuoti tokiu pačiu būdu.
2 pavyzdys: Duomenų išgava manipuliuojant identifikatoriais
Informacijos paieška duomenų bazėje pagal ID yra praktiškas ir plačiai naudojamas metodas, tačiau kartu sudaro galimybes SQL įterpimui. Pavyzdžiui, žiniatinklio serveris pagal URL adrese perduotą ID žino, kokią informaciją turi iškviesti iš duomenų bazės. Atitinkamas PHP skriptas atrodo taip:
<?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);
}
?>phpTikėtinas URL atitinka .../script.php?id=22 šabloną. Šiuo atveju būtų iškeltas lentelės įrašas su ID „22“. Jei neįgaliotas asmuo turėtų galimybę pakeisti šį URL ir vietoj to išsiųstų užklausą, pavyzdžiui, kaip .../script.php?id=22+OR+1=1, dėl to būtų iškeltos visos lentelės eilutės:
SELECT * FROM table WHERE id=22 OR 1=1;sqlKaip nusikaltėliai suranda pažeidžiamas duomenų bazių sistemas?
Iš esmės bet kuri svetainė ar internetinė programa, kurioje naudojamos SQL duomenų bazės be iš anksto paruoštų užklausų (prepared statements) ar kitų apsaugos priemonių, gali būti pažeidžiama SQL įterpimo atakoms. Atrastos pažeidžiamybės pasauliniame tinkle ilgai paslėptos nelieka. Iš tiesų yra svetainių, kurios skelbia naujausius žinomų saugumo spragų sąrašus ir net paaiškina, kaip įsilaužėliai gali pasinaudoti „Google“ paieška, kad surastų atitinkančius internetinius projektus. Jei svetainė pateikia išsamius SQL klaidų pranešimus, kibernetiniai nusikaltėliai gali juos panaudoti potencialioms pažeidžiamoms vietoms nustatyti. Pavyzdžiui, pridėjus apostrofą prie URL, kuriame yra ID parametras, gali būti atskleista silpnoji vieta, kaip parodyta šiame pavyzdyje:
[DomainName].com/news.php?id=5’Pažeidžiama svetainė grąžina klaidos pranešimą tokia forma:
Query failed: You have an error in your SQL syntax…
Panašūs metodai taip pat gali būti naudojami stulpelių skaičiui, lentelių ir stulpelių pavadinimams, SQL versijai ar net vartotojų vardams ir slaptažodžiams išgauti. Be to, yra įvairių įrankių, kurie gali automatizuoti tiek paieškos procesą, tiek SQL įterpimo atakų vykdymą.
Kaip apsaugoti duomenų bazę nuo SQL įterpimo
Yra įvairių metodų, kuriuos galite taikyti, siekdami užkirsti kelią SQL įterpimo atakoms prieš jūsų duomenų bazių sistemą. Turėtumėte atsižvelgti į visus susijusius komponentus – serverį, atskiras programas ir duomenų bazių valdymo sistemą.
1 žingsnis: stebėti automatinius duomenų įvedimus iš programų
Apdorojant iš išorinių ar įterptųjų programų gaunamus duomenis, būtina patikrinti ir filtruoti pateiktas reikšmes, kad būtų išvengta SQL įterpimų.
1. Patikrinti duomenų tipus
Kiekvienas įvesties duomenų elementas turi atitikti numatytą duomenų tipą. Pavyzdžiui, jei reikalaujama įvesti skaičių, paprastas patikrinimas PHP kalba galėtų atrodyti taip:
if (filter_var($input, FILTER_VALIDATE_INT) === false) {
throw new InvalidArgumentException("Invalid input");
}phpTokios patikros turėtų būti atliekamos ir su eilutėmis, datomis ar kitais specifiniais formatais.
2. Filtruoti specialiuosius simbolius
Specialieji simboliai gali sukelti saugumo pažeidžiamumą, ypač SQL ar HTML kontekste. Saugus sprendimas – naudoti htmlspecialchars() HTML įvestims ir PDO::quote() SQL užklausoms.
3. Stenkitės nerodyti klaidų pranešimų
Reikėtų vengti tiesioginių klaidų pranešimų, kuriuose atskleidžiami techniniai duomenų bazės ar sistemos duomenys. Vietoj to reikėtų rodyti bendro pobūdžio pranešimą, pavyzdžiui:
echo "An error occurred. Please try again later.";
error_log("Unexpected error encountered. See system log for details.");php4. Naudokite paruoštus teiginius
Vienas iš veiksmingiausių būdų išvengti SQL įterpimų – naudoti paruoštus teiginius. Taikant šį metodą, SQL komandos ir parametrai siunčiami atskirai, todėl piktavališkas kodas negali būti vykdomas. Štai pavyzdinis įgyvendinimas PHP kalba naudojant PDO (PHP Data Objects):
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(':id', $user_id, PDO::PARAM_INT);
$stmt->execute();phpDuomenų bazių valdymo sistema automatiškai užtikrina, kad įvesties duomenys būtų apdorojami saugiai.
2 žingsnis: Užtikrinkite visapusišką serverio apsaugą
Serverio, kuriame veikia jūsų duomenų bazių valdymo sistema, saugumas taip pat atlieka lemiamą vaidmenį užkertant kelią SQL įterpimui. Viena iš pagrindinių priemonių – sustiprinti operacinę sistemą, laikantis šių geriausios praktikos rekomendacijų:
- Įdiekite arba įjunkite tik tas programas ir paslaugas, kurios yra būtinos duomenų bazės veikimui.
- Pašalinkite visas nenaudojamas arba nereikalingas vartotojo paskyras.
- Užtikrinkite, kad visi reikalingi sistemos ir programinės įrangos atnaujinimai būtų įdiegiami nedelsiant.
- Taikykite mažiausių teisių principą, kad vartotojams ir paslaugoms būtų suteiktos tik būtiniausios teisės.
Atsižvelgiant į jūsų internetinio projekto saugumo reikalavimus, reikėtų apsvarstyti papildomas apsaugos priemones:
- Įsilaužimų aptikimo sistemos (IDS) ir įsilaužimų prevencijos sistemos (IPS): Šios sistemos naudoja įvairius aptikimo metodus, kad anksti nustatytų atakas, išsiųstų įspėjimus ir – naudojant IPS – automatiškai imtųsi atsakomųjų priemonių.
- Taikomosios programos sluoksnio šliuzas (ALG): ALG stebi ir filtruoja srautą tarp taikomųjų programų ir žiniatinklio naršyklių tiesiogiai taikomosios programos lygiu.
- Tinklo programų užkarda (WAF): WAF specialiai apsaugo tinklo programas nuo SQL įterpimo ir tarpvetainių skriptų (XSS), blokuodama arba valydama įtartinus užklausimus.
- „Zero Trust“ metodas: šis modernus saugumo modelis užtikrina, kad kiekvienas bandymas prisijungti – nepriklausomai nuo jo kilmės – būtų patikrintas ir autentiškumas patvirtintas prieš suteikiant prieigą.
- Ugniasienės taisyklės ir tinklo segmentavimas: tai yra būtina norint ilgalaikėje perspektyvoje sumažinti atakų paviršių.
- Reguliarūs IT saugumo auditai ir įsilaužimo testai: jie padeda anksti aptikti ir pašalinti pažeidžiamumą.
3 žingsnis: Užtikrinkite duomenų bazės saugumą ir naudokite saugų kodą
Kaip ir operacinė sistema, duomenų bazė turi būti išvalyta nuo visų nereikalingų komponentų ir nuolat atnaujinama. Pašalinkite visas nereikalingas saugomas procedūras ir išjunkite visas nenaudojamas paslaugas bei vartotojų paskyras. Sukurkite specialią duomenų bazės paskyrą, skirtą tik prieigai per internetą, ir suteikite jai tik būtiniausias teises.
Atsižvelgiant į parengtų užklausų naudojimą, primygtinai rekomenduojama nenaudoti „PHP mysql modulio (kuris buvo pašalintas iš PHP 7). Vietoj to rinkitės mysqli arba PDO, kad užtikrintumėte didesnį saugumą ir suderinamumą. Saugi mysqli užklausa galėtų atrodyti taip:
$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();phpSlaptažodžiai jokiu būdu neturėtų būti saugomi tiesiogiai duomenų bazėje arba išsaugomi paprastojo teksto formatu. Vietoj to, naudokite maišymo metodą, pavyzdžiui, password_hash(), kartu su password_verify(), kad saugiai apsaugotumėte prisijungimo duomenis. Saugus įgyvendinimas galėtų atrodyti taip:
$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.";
}phpKoks ryšys tarp „Bobby“ stalelių ir SQL įterpimo?
Svetainė bobby-tables.com naudoja internetinį komiksą „xkcd“, kad juokingai iliustruotų pavojus, kylančius dėl nesaugių vartotojo įvesties duomenų duomenų bazėse. Komikse motina gauna skambutį iš savo sūnaus (mylimai vadinamo „Little Bobby Tables“) mokyklos. Skambintojas paklausia, ar jos sūnaus vardas tikrai yra Robert'); DROP TABLE Students;--, o ji atsako, kad taip. Skambučio priežastis netrukus paaiškėja: bandant įvesti vardą „Robert“ į mokinių duomenų bazę, buvo ištrinta visa mokinių lentelė. Motina nėra pernelyg užjaučianti – ji tiesiog tikisi, kad mokykla išmoko pamoką ir ateityje valys duomenų bazės įvestis.
Ši karikatūra aiškiai parodo katastrofiškas pasekmes, kurios gali kilti, jei duomenų bazių programose vartotojo įvestys nėra tinkamai patikrintos ir išvalytos.