Kas ir SQL injekcija?
SQL-injekcijas rada būtisku apdraudējumu relāciju datubāzu modeļiem un tajos esošajai konfidenciālajai informācijai. Tāpēc ir absolūti nepieciešama visaptveroša aizsardzība pret šiem neatļautiem ārējiem piekļuves mēģinājumiem, kurus padara iespējamus drošības ievainojamības.
Kas ir SQL injekcija?
SQL injekcija ir uzbrukuma veids, kas izmanto drošības ievainojamību relatīvo datubāzu sistēmās, kuras lieto SQL vaicājumu valodu lietotāja ievadīto datu apstrādei. Uzbrucējs izmanto lietotāju ievadītos datus, kas nav pareizi attīrīti un satur īpašus simbolus, piemēram, dubultos defises, pēdiņas vai semikolonu. Šiem simboliem ir īpašas funkcijas SQL interpretatorā, un tie ļauj ārēji manipulēt ar izpildāmajām komandām. SQL injekcijas bieži saistās ar PHP un ASP lietojumprogrammām, kas balstās uz novecojušām saskarnēm. Daudzos šādos gadījumos ievadītie dati netiek pienācīgi attīrīti, padarot tos par galveno uzbrukuma mērķi.
Stratēģiski ievietojot funkciju simbolus, neatļauts lietotājs var ievadīt papildu SQL komandas un manipulēt ar datu bāzes ierakstiem, lai lasītu, mainītu vai dzēstu datus. Smagākos gadījumos uzbrucēji var pat iegūt piekļuvi sistēmas komandu rindai, kas ļautu viņiem pārņemt pilnīgu kontroli pār datu bāzes serveri.
SQL injekcijas piemērs, kas parāda, kā darbojas uzbrukums datu bāzei
Tā kā neaizsargātus datubāzes serverus var ātri identificēt un SQL injekcijas uzbrukumus ir salīdzinoši viegli veikt, šī metode joprojām ir viena no visplašāk izmantotajām metodēm kibernoziedznieku vidū visā pasaulē. Uzbrucēji izmanto dažādas stratēģijas, izmantojot gan nesen atklātus, gan jau sen zināmus drošības trūkumus lietojumprogrammās, kas iesaistītas datu pārvaldības procesā. Lai labāk izprastu, kā SQL injekcija darbojas praksē, aplūkosim divas izplatītas uzbrukuma metodes kā piemērus.
1. piemērs: Piekļuve, izmantojot nepareizi attīrītu lietotāja ievadīto informāciju
Lai piekļūtu datu bāzei, lietotājiem parasti vispirms ir jāautentificējas. Šim nolūkam parasti izmanto skriptus, kas parāda pieteikšanās veidlapu ar laukiem lietotājvārdam un parolai. Lietotāji aizpilda formu, un skripts pēc tam pārbauda, vai datu bāzē ir atbilstoši ieraksti. Pēc noklusējuma datu bāzē var būt tabula ar nosaukumu users un kolonnām username un password. Tipiskā tīmekļa lietojumprogrammā attiecīgās skripta rindas datu bāzes piekļuvei (izmantojot Python līdzīgu pseidokodu) var izskatīties šādi:
uname = request.POST['username']
passwd = request.POST['password']
sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + passwd + "'"
database.execute(sql)pythonTagad uzbrucējs var manipulēt ar paroles lauku, izmantojot SQL injekciju, piemēram, ievadot password' OR 1='1, kas izraisa šādu SQL vaicājumu:
sql = "SELECT id FROM users WHERE username='' AND password='password' OR 1='1'"pythonTas uzbrucējam nodrošina pilnīgu piekļuvi visai lietotāju tabulai datu bāzē, jo paroles nosacījums vienmēr izvērtējas kā patiesība (1='1'). Ja uzbrucējs piesakās kā administrators, viņš var brīvi mainīt jebkuru ierakstu datu bāzē. Tāpat var manipulēt arī ar lietotājvārda lauku.
2. piemērs: Datu izgūšana, manipulējot ar identifikatoriem
Informācijas izgūšana no datu bāzes pēc identifikatora ir praktiska un izplatīta metode, taču tā arī rada iespējamu risku SQL injekcijas uzbrukumiem. Piemēram, tīmekļa serveris, izmantojot URL adresē nosūtīto identifikatora informāciju, zina, kādu informāciju tam jāizgūst no datu bāzes. Atbilstošais PHP skripts izskatās šādi:
<?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);
}
?>phpParedzētais URL atbilst paraugam .../script.php?id=22. Šajā gadījumā tiktu izgūts tabulas ieraksts ar ID „22”. Ja neatļautai personai ir iespēja manipulēt ar šo URL un tā vietā nosūta pieprasījumu, piemēram, .../script.php?id=22+OR+1=1, rezultātā izpildītais vaicājums izraisīs visu tabulas rindu izgūšanu:
SELECT * FROM table WHERE id=22 OR 1=1;sqlKā noziedznieki atrod neaizsargātas datu bāzes sistēmas?
Principā jebkura tīmekļa vietne vai tīmekļa lietojumprogramma, kas izmanto SQL datu bāzes bez sagatavotiem vaicājumiem (prepared statements) vai citiem aizsardzības pasākumiem, var būt neaizsargāta pret SQL injekcijām. Atklātās ievainojamības tīmeklī ilgi nepaliek nepamanītas. Patiesībā ir tīmekļa vietnes, kas publicē atjauninātus sarakstus ar zināmajiem drošības trūkumiem — un pat izskaidro, kā uzbrucēji var izmantot Google meklēšanu, lai atrastu atbilstošus tīmekļa projektus. Ja tīmekļa vietne atgriež detalizētus SQL kļūdu ziņojumus, kibernoziedznieki var izmantot šos ziņojumus, lai identificētu potenciālos ievainojamības punktus. Piemēram, apostrofa pievienošana URL galam, kas ietver ID parametru, jau var atklāt vājumu, kā parādīts šajā piemērā:
[DomainName].com/news.php?id=5’Neaizsargāta tīmekļa vietne atgriež kļūdas ziņojumu šādā formā:
Query failed: You have an error in your SQL syntax…
Līdzīgas metodes var izmantot arī, lai iegūtu kolonnu skaitu, tabulu un kolonnu nosaukumus, SQL versiju vai pat lietotājvārdus un paroles. Turklāt ir pieejami dažādi rīki, kas spēj automatizēt gan uzlaužamo vietu meklēšanas procesu, gan SQL injekcijas uzbrukumu izpildi.
Kā pasargāt savu datu bāzi no SQL-injekcijas
Ir dažādas metodes, ko varat izmantot, lai novērstu SQL injekcijas uzbrukumus savai datu bāzes sistēmai. Jums jāpievēršas visām iesaistītajām sastāvdaļām – gan serverim un atsevišķām lietojumprogrammām, gan datu bāzes pārvaldības sistēmai.
1. solis: Automātisko datu ievadi no lietojumprogrammām
Apstrādājot datus no ārējām vai iebūvētajām lietojumprogrammām, ir būtiski pārbaudīt un filtrēt iesniegtās vērtības, lai novērstu SQL-injekcijas.
1. Pārbaudīt datu tipus
Katram ievades laukam jāatbilst paredzētajam datu tipam. Piemēram, ja ir nepieciešama skaitliska ievade, vienkārša pārbaude PHP varētu izskatīties šādi:
if (filter_var($input, FILTER_VALIDATE_INT) === false) {
throw new InvalidArgumentException("Invalid input");
}phpLīdzīgas pārbaudes būtu jāievieš arī attiecībā uz teksta virknēm, datumiem vai citiem specifiskiem formātiem.
2. Filtrēt īpašos simbolus
Īpašie simboli var radīt drošības risku, jo īpaši SQL vai HTML vidē. Droša pieeja ir izmantot htmlspecialchars() HTML ievadei un PDO::quote() SQL vaicājumiem.
3. Izvairieties no kļūdu ziņojumu parādīšanas
Jāizvairās no tiešiem kļūdu ziņojumiem, kuros tiek atklātas tehniskas detaļas par datu bāzi vai sistēmu. Tā vietā jāparāda vispārīgs ziņojums, piemēram:
echo "An error occurred. Please try again later.";
error_log("Unexpected error encountered. See system log for details.");php4. Izmantojiet sagatavotus vaicājumus
Viens no visefektīvākajiem veidiem, kā novērst SQL injekcijas, ir sagatavoto izteikumu izmantošana. Šajā pieejā SQL komandas un parametri tiek nosūtīti atsevišķi, tādējādi ļaunprātīgs kods nevar tikt izpildīts. Šeit ir īss īstenojuma piemērs PHP, izmantojot PDO (PHP Data Objects):
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(':id', $user_id, PDO::PARAM_INT);
$stmt->execute();phpDatu bāzes pārvaldības sistēma automātiski nodrošina, ka ievadītie dati tiek apstrādāti droši.
2. solis: Nodrošiniet visaptverošu servera aizsardzību
SQL injekciju novēršanā būtiska nozīme ir arī tā servera drošībai, kurā darbojas jūsu datubāzes pārvaldības sistēma. Viens no galvenajiem pasākumiem ir operētājsistēmas drošības pastiprināšana, ievērojot šādus ieteikumus:
- Instalējiet vai aktivizējiet tikai tās lietojumprogrammas un pakalpojumus, kas ir nepieciešami datu bāzes darbībai.
- Dzēst visus neizmantotos vai nevajadzīgos lietotāju kontus.
- Nodrošiniet, ka visi attiecīgie sistēmas un programmatūras atjauninājumi tiek instalēti nekavējoties.
- Piemērojiet minimālo privilēģiju principu, lai nodrošinātu, ka lietotājiem un pakalpojumiem tiek piešķirtas tikai minimālās nepieciešamās atļaujas.
Atkarībā no jūsu tīmekļa projekta drošības prasībām, jums vajadzētu apsvērt papildu aizsardzības pasākumus:
- Iebrukuma atklāšanas sistēmas (IDS) un iebrukuma novēršanas sistēmas (IPS): Šīs sistēmas izmanto dažādas atklāšanas metodes, lai savlaicīgi identificētu uzbrukumus, izsūtītu brīdinājumus un — ja tiek izmantota IPS — automātiski uzsāktu pretpasākumus.
- Lietojumprogrammu slāņa vārteja (ALG): ALG uzrauga un filtrē datplūsmu starp lietojumprogrammām un tīmekļa pārlūkprogrammām tieši lietojumprogrammu līmenī.
- Tīmekļa lietojumprogrammu ugunsmūris (WAF): WAF īpaši aizsargā tīmekļa lietojumprogrammas no SQL injekcijas un starplapju skriptēšanas (XSS), bloķējot vai attīrot aizdomīgus pieprasījumus.
- Zero Trust pieeja: Šis modernais drošības modelis nodrošina, ka katrs piekļuves mēģinājums — neatkarīgi no tā izcelsmes — tiek pārbaudīts un autentificēts, pirms tiek piešķirta piekļuve.
- Ugunsmūra noteikumi un tīkla segmentācija: Tie ir būtiski, lai ilgtermiņā samazinātu uzbrukumu risku.
- Regulāras IT drošības revīzijas un iekļūšanas testi: Tie palīdz agrīnā stadijā atklāt un novērst ievainojamības.
3. solis: Datubāzes drošības pastiprināšana un droša koda izmantošana
Tāpat kā operētājsistēmai, arī datu bāzei ir jāatbrīvojas no visām nevajadzīgajām sastāvdaļām un jāuztur atjaunināta. Izdzēsiet visas nevajadzīgās saglabātās procedūras un atspējojiet visus neizmantotos pakalpojumus un lietotāju kontus. Izveidojiet īpašu datu bāzes kontu, kas paredzēts vienīgi tīmekļa piekļuvei, un piešķiriet tam tikai minimālās nepieciešamās atļaujas.
Ņemot vērā sagatavoto vaicājumu izmantošanu, tiek stingri ieteikts neizmantot mysql PHP moduli (kas tika izņemts no PHP 7). Tā vietā izvēlieties mysqli vai PDO, lai nodrošinātu labāku drošību un saderību. Drošs mysqli vaicājums varētu izskatīties šādi:
$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();phpParoles nekad nedrīkst glabāt tieši datu bāzē vai izgūt nešifrētā veidā. Tā vietā izmantojiet hašēšanas metodi, piemēram, password_hash(), kopā ar password_verify(), lai droši aizsargātu piekļuves datus. Droša īstenošana varētu izskatīties šādi:
$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.";
}phpKāda saistība ir bobby galdiem ar SQL injekciju?
Tīmekļa vietne bobby-tables.com izmanto xkcd tīmekļa komiksu, lai ar humoru ilustrētu nedrošas lietotāju ievadīto datu radītos draudus datu bāzēs. Komiksā māte saņem zvanu no sava dēla (mīļi saukta par Little Bobby Tables) skolas. Zvanītājs jautā, vai viņas dēla vārds patiešām ir Robert'); DROP TABLE Students;--, uz ko viņa atbild apstiprinoši. Zvanīšanas iemesls drīz kļūst skaidrs: mēģinājums ievadīt vārdu Robert skolēnu datu bāzē izraisīja visu skolēnu tabulu dzēšanu. Māte nav pārāk saprotoša — viņa vienkārši cer, ka skola ir guvusi mācību un turpmāk pārbaudīs datu bāzes ievadi.
Komikss skaidri parāda katastrofālās sekas, kas var rasties, ja datubāzes lietojumprogrammās netiek pienācīgi pārbaudīti un attīrīti lietotāju ievadītie dati.