Injecțiile SQL reprezintă o amenințare semnificativă pentru modelele de baze de date relaționale și pentru informațiile sensibile pe care le conțin. De aceea, protecția completă împotriva acestor tentative de acces extern neautorizat, posibilă datorită vulnerabilităților de securitate, este absolut esențială.

Ce este o injecție SQL?

O injecție SQL este un tip de atac care exploatează o vulnerabilitate de securitate în sistemele de baze de date relaționale care utilizează limbajul de interogare SQL pentru a procesa datele introduse de utilizator. Atacatorul profită de datele introduse de utilizatori care nu sunt escapate corespunzător și conțin caractere speciale, cum ar fi cratime duble, ghilimele sau punct și virgulă. Aceste caractere au funcții speciale pentru interpretorul SQL și permit manipularea externă a comenzilor executate. Injectările SQL sunt adesea asociate cu aplicații PHP și ASP care se bazează pe interfețe învechite. În multe dintre aceste cazuri, datele introduse nu sunt curățate corespunzător, ceea ce le face o țintă principală pentru un atac.

Prin inserarea strategică a caracterelor funcționale, un utilizator neautorizat poate introduce comenzi SQL suplimentare și manipula intrările din baza de date pentru a citi, modifica sau șterge date. În cazuri grave, atacatorii pot chiar obține acces la linia de comandă a sistemului, ceea ce le poate permite să preia controlul deplin asupra serverului bazei de date.

Exemplu de injecție SQL care arată cum funcționează un atac asupra bazei de date

Deoarece serverele de baze de date vulnerabile pot fi identificate rapid și atacurile de tip SQL injection sunt relativ ușor de executat, această metodă rămâne una dintre cele mai utilizate tehnici în rândul infractorilor cibernetici din întreaga lume. Atacatorii folosesc diverse strategii, exploatând atât vulnerabilități de securitate recent descoperite, cât și vulnerabilități vechi din aplicațiile implicate în procesul de gestionare a datelor. Pentru a înțelege mai bine cum funcționează SQL injection în practică, să analizăm două metode comune de atac ca exemple.

Exemplul 1: Acces prin intermediul unei intrări de utilizator slab protejată

Pentru a accesa o bază de date, utilizatorii trebuie de obicei să se autentifice mai întâi. În acest scop, se utilizează frecvent scripturi pentru a afișa un formular de autentificare care include un câmp pentru numele de utilizator și unul pentru parolă. Utilizatorii completează formularul, iar scriptul verifică apoi dacă există intrări corespunzătoare în baza de date. În mod implicit, baza de date poate conține un tabel numit users cu coloanele username și password. Într-o aplicație web tipică, liniile de script relevante pentru accesul la baza de date (utilizând pseudocod de tip Python) ar putea arăta astfel:

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

Un atacator poate acum manipula câmpul parolei folosind o injecție SQL, de exemplu introducând password' OR 1='1, ceea ce duce la următoarea interogare SQL:

sql = "SELECT id FROM users WHERE username='' AND password='password' OR 1='1'"
python

Acest lucru îi oferă atacatorului acces complet la întregul tabel de utilizatori din baza de date, deoarece condiția parolei este întotdeauna evaluată ca fiind adevărată (1='1'). Dacă atacatorul se conectează ca administrator, poate modifica liber orice intrare din baza de date. Alternativ, câmpul numelui de utilizator poate fi manipulat în același mod.

Exemplul 2: Extragerea datelor prin manipularea ID-ului

Interogarea informațiilor dintr-o bază de date după ID este o metodă practică și obișnuită, dar deschide și o posibilă poartă pentru injecția SQL. De exemplu, un server web știe, prin intermediul unui detaliu ID transmis într-o adresă URL, ce informații trebuie să recupereze din baza de date. Scriptul PHP corespunzător arată astfel:

<?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

URL-ul așteptat urmează modelul .../script.php?id=22. În acest caz, ar fi recuperată intrarea din tabel cu ID-ul „22”. Dacă o persoană neautorizată are posibilitatea de a manipula acest URL și trimite în schimb o solicitare precum .../script.php?id=22+OR+1=1, interogarea rezultată va determina recuperarea tuturor rândurilor din tabel:

SELECT * FROM table WHERE id=22 OR 1=1;
sql

Cum găsesc infractorii sistemele de baze de date vulnerabile?

În principiu, orice site web sau aplicație web care utilizează baze de date SQL fără interogări pregătite (declarații pregătite) sau alte măsuri de protecție poate fi vulnerabil la injecții SQL. Vulnerabilitățile descoperite nu rămân ascunse mult timp pe World Wide Web. De fapt, există site-uri web care publică liste actualizate cu defecte de securitate cunoscute și chiar explică modul în care atacatorii pot utiliza căutările Google pentru a găsi proiecte web potrivite. Dacă un site web returnează mesaje detaliate de eroare SQL, infractorii cibernetici pot utiliza aceste mesaje pentru a identifica potențiale vulnerabilități. De exemplu, adăugarea unui apostrof la sfârșitul unei adrese URL care include un parametru ID poate deja expune o slăbiciune, așa cum se arată în exemplul următor:

[DomainName].com/news.php?id=5’

Un site web vulnerabil trimite un mesaj de eroare în forma următoare:

Query failed: You have an error in your SQL syntax…

Metode similare pot fi utilizate și pentru a extrage numărul de coloane, numele tabelelor și coloanelor, versiunea SQL sau chiar numele de utilizator și parolele. În plus, există diverse instrumente care pot automatiza atât procesul de descoperire, cât și executarea atacurilor de tip SQL injection.

Cum să vă protejați baza de date împotriva injecțiilor SQL

Există diverse metode pe care le puteți utiliza pentru a preveni atacurile de tip SQL injection asupra sistemului dvs. de baze de date. Trebuie să vă ocupați de toate componentele implicate – serverul și aplicațiile individuale, precum și sistemul de gestionare a bazelor de date.

Pasul 1: Monitorizați intrările automate din aplicații

Atunci când se procesează intrări din aplicații externe sau încorporate, este esențial să se valideze și să se filtreze valorile trimise pentru a preveni injecțiile SQL.

1. Validați tipurile de date

Fiecare intrare trebuie să corespundă tipului de date așteptat. De exemplu, dacă este necesară o intrare numerică, o validare simplă în PHP ar putea arăta astfel:

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

Verificări similare ar trebui implementate pentru șiruri de caractere, date sau alte formate specifice.

2. Filtrează caracterele speciale

Caracterele speciale pot crea vulnerabilități de securitate, în special în contextele SQL sau HTML. O abordare sigură este utilizarea htmlspecialchars() pentru introducerea HTML și a PDO::quote() pentru interogările SQL.

3. Evitați să dezvăluiți mesaje de eroare

Mesajele de eroare directe care dezvăluie detalii tehnice despre baza de date sau sistem trebuie evitate. În schimb, afișați un mesaj generic, cum ar fi:

echo "An error occurred. Please try again later.";
error_log("Unexpected error encountered. See system log for details.");
php

4. Utilizați declarații pregătite

Una dintre cele mai eficiente metode de prevenire a injecțiilor SQL este utilizarea instrucțiunilor pregătite. În această abordare, comenzile și parametrii SQL sunt trimiși separat, astfel încât codul rău intenționat nu poate fi executat. Iată un exemplu de implementare în PHP utilizând PDO (PHP Data Objects):

$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(':id', $user_id, PDO::PARAM_INT);
$stmt->execute();
php

Sistemul de gestionare a bazelor de date asigură automat procesarea sigură a datelor introduse.

Pasul 2: Asigurați-vă protecția completă a serverului

Securitatea serverului pe care rulează sistemul de gestionare a bazelor de date joacă, de asemenea, un rol crucial în prevenirea injecțiilor SQL. O măsură esențială este consolidarea sistemului de operare urmând aceste bune practici:

  • Instalați sau activați numai aplicațiile și serviciile esențiale pentru rularea bazei de date.
  • Eliminați toate conturile de utilizator neutilizate sau inutile.
  • Asigurați-vă că toate actualizările relevante ale sistemului și software-ului sunt instalate prompt.
  • Aplicați principiul privilegiului minim pentru a vă asigura că utilizatorilor și serviciilor li se acordă numai permisiunile minime necesare.

În funcție de cerințele de securitate ale proiectului dvs. web, ar trebui să luați în considerare măsuri de protecție suplimentare:

  • Sisteme de detectare a intruziunilor (IDS) și sisteme de prevenire a intruziunilor (IPS): aceste sisteme utilizează diverse metode de detectare pentru a identifica atacurile din timp, a emite alerte și, în cazul utilizării IPS, a iniția automat contramăsuri.
  • Application Layer Gateway (ALG): Un ALG monitorizează și filtrează traficul între aplicații și browsere web direct la nivel de aplicație.
  • Web Application Firewall (WAF): Un WAF protejează în mod specific aplicațiile web împotriva injecțiilor SQL și Cross-Site Scripting (XSS) prin blocarea sau curățarea cererilor suspecte.
  • Abordarea Zero Trust: acest model modern de securitate asigură că fiecare încercare de acces, indiferent de originea sa, este verificată și autentificată înainte de acordarea accesului.
  • Reguli de firewall și segmentarea rețelei: acestea sunt esențiale pentru minimizarea suprafeței de atac pe termen lung.
  • Audituri regulate de securitate IT și teste de penetrare: acestea ajută la detectarea și remedierea vulnerabilităților într-un stadiu incipient.

Pasul 3: Consolidați baza de date și utilizați coduri sigure

La fel ca sistemul de operare, baza de date trebuie să fie curățată de toate componentele inutile și menținută la zi. Eliminați toate procedurile stocate de care nu aveți nevoie și dezactivați toate serviciile și conturile de utilizator neutilizate. Creați un cont dedicat bazei de date destinat exclusiv accesului web și atribuiți-i doar permisiunile minime necesare.

În conformitate cu utilizarea instrucțiunilor pregătite, se recomandă insistent să nu utilizați modulul mysql PHP (care a fost eliminat în PHP 7). În schimb, optați pentru mysqli sau PDO pentru a asigura o mai bună securitate și compatibilitate. O interogare mysqli sigură ar putea arăta astfel:

$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

Parolele nu trebuie niciodată stocate direct într-o bază de date sau recuperate în format text simplu. În schimb, utilizați o metodă de hash, cum ar fi password_hash(), în combinație cu password_verify(), pentru a proteja în siguranță datele de autentificare. O implementare sigură ar putea arăta astfel:

$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

Ce legătură au tabelele bobby cu injecția SQL?

Site-ul web bobby-tables.com folosește o bandă desenată xkcd pentru a ilustra în mod amuzant pericolele introducerii nesigure a datelor de către utilizatori în bazele de date. În banda desenată, o mamă primește un telefon de la școala fiului ei (cunoscut afectuos sub numele de Little Bobby Tables). Apelantul o întreabă dacă fiul ei se numește într-adevăr Robert'); DROP TABLE Students;--, la care ea răspunde afirmativ. Motivul apelului devine curând clar: încercarea de a introduce numele Robert în baza de date a elevilor a dus la ștergerea întregii tabele cu elevi. Mama nu este prea înțelegătoare – ea speră doar că școala a învățat lecția și că va verifica datele introduse în baza de date pe viitor.

Comicul evidențiază în mod clar consecințele catastrofale care pot rezulta din validarea și igienizarea necorespunzătoare a datelor introduse de utilizatori în aplicațiile de baze de date.

Mergi la meniul principal