Mulți developeri web nu știu cum pot fi manipulate interpelările SQL, și acordă toata încrederea unei asemenea comenzi. Interpelările SQL pot ocoli controalele de acces, în consecință să treacă peste metodele de autentificare și verificările de autorizație, iar câteodată pot chiar să faciliteze accesul la comenzile de sistem.
Injectarea directă a comenzilor SQL este o tehnică în care atacatorul creează sau modifică comenzile SQL pentru a scoate la iveală datele sensibile, sau pentru a suprascrie o anumită valoare, sau chiar pentru a executa comenzi periculoase la nivel de sistem. Acest lucru este înfaptuit de către aplicația care preia inputul utilizatorului, îl combină cu parametrii statici pentru a forma o interpelare SQL. Următoarele exemple sunt bazate pe cazuri reale, cu regret.
Datorită lipsei validării inputului și conectării la baza de date cu drepturi de superuser, sau a unui user care poate crea la rândul lui alți useri, atacatorul poate crea un superuser în baza de date.
Example #1 Împărțirea rezultatelor în mai multe pagini ... și crearea de superuseri (PostgreSQL)
<?php
$offset = argv[0]; // atentie, nu se face validarea inputului!
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = pg_query($conn, $query);
?>
0; insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd) select 'crack', usesysid, 't','t','crack' from pg_shadow where usename='postgres'; --
Notă:
Este o tehnică obișnuită de a forța parserul SQL să ignore restul interpelării scrise de developer, cu ajutorul --, care este simbolul pentru comentariu în SQL.
O reală posibilitate de a afla parole este de a manipula rezultatele din paginile de căutare. Singurul lucru de care are nevoie atacatorul este să vadă dacă există variabile în declarațiile SQL care nu sunt protejate corespunzător. Se pot manipula variabilele din formularele care utilizează WHERE, ORDER BY, LIMIT sau condițiile OFFSET din declarațiile SELECT. Dacă baza de date suportă construcții UNION, atacatorul poate încerca să lipească o interpelare întreagă la cea originală pentru a lista parolele dintr-un tabel arbitrar. Folosirea parolelor criptate este pe deplin încurajată.
Example #2 Listarea unor articole ... și a unor parole (orice server de baze de date)
<?php
$query = "SELECT id, name, inserted, size FROM products
WHERE size = '$size'";
$result = odbc_exec($conn, $query);
?>
' union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable; --
Comanda SQL UPDATE nu este nici ea ocolită de probleme. Aceste interpelări sunt amenințate de atacurile prin tăierea și alipirea unei noi interpelări. În plus, atacatorul se mai poate juca și cu declarația SET. În acest caz, atacatorul trebuie să cunoască careva informații despre schemă, de ex. structura tabelului din care dorește să extragă sau să manipuleze informația. Acest lucru poate fi facut prin examinarea denumirilor variabilelor din formulare, sau prin procedeul brute-force. Nu există multe convenții prin care se delimitează câmpurile pentru user sau parolă.
Example #3 De la resetarea unei parole ... până la obținerea mai multor privilegii (orice server de baze de date)
<?php
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
?>
<?php
// $uid: ' or uid like '%admin%
$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%';";
// $pwd: hehehe', trusted=100, admin='yes
$query = "UPDATE usertable SET pwd='hehehe', trusted=100, admin='yes' WHERE
...;";
?>
Un exemplu înspăimântător despre cum pot fi rulate comenzi la nivel de sistem de operare pe unele servere de baze de date.
Example #4 Atacarea sistemului de operare pe care lucrează baza de date (MSSQL Server)
<?php
$query = "SELECT * FROM products WHERE id LIKE '%$prod%'";
$result = mssql_query($query);
?>
<?php
$query = "SELECT * FROM products
WHERE id LIKE '%a%'
exec master..xp_cmdshell 'net user test testpass /ADD'--";
$result = mssql_query($query);
?>
Notă:
Unele dintre exemplele de mai sus sunt legate de anumite servere de baze de date. Acest lucru nu înseamnă că atacuri similare nu pot avea loc asupra altor produse similare lor. Serverul dumneavoastră de baze de date poate fi vulnerabil într-o manieră asemănătoare.
Cu toate că este evident că un atacator trebuie să posede cel puțin careva cunoștințe în privința arhitecturii bazei de date pentru a desfășura un atac cu succes, obținerea acestei informații este deseori foarte simplă. Spre exemplu, dacă o bază de date face parte dintr-un pachet software cu sursă deschisă, sau disponibilă publicului larg, cu o instalare implicită, această informație este absolut deschisă și disponibilă tuturor. Această informație poate de asemenea să fie divulgată de un cod-sursă închis - chiar dacă este codificat, camuflat sau compilat - și chiar de propriul dumneavoastră cod prin afișarea mesajelor de eroare. Alte metode includ utilizarea numelor răspândite pentru tabele și coloane. Spre exemplu, un formular de login care utilizează un tabel 'users' cu denumirile coloanelor 'id', 'username' și 'password'.
Aceste atacuri sunt de obicei bazate pe exploatarea codului scris de developeri fără a lua în calcul securitatea lui. Niciodată nu aveți încredere în nici un fel de input, mai ales când acesta provine din partea clientului, chiar dacă acesta vine dintr-un câmp select, câmp ascuns sau cookie. Primul exemplu arată că o interpelare aparent nevinovată poate cauza un dezastru.
Dacă aplicația așteaptă un input numeric, încercați să verificați datele cu funcția ctype_digit(), sau schimbați tipul variabilei utilizând funcția settype(), sau folosiți reprezentația numerică prin sprintf().
Example #5 O metodă mai sigură de formare a interpelării pentru paginare
<?php
settype($offset, 'integer');
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
// observați %d (care înseamnă formatul integer) din string-ul de formatare,
// folosirea %s (string) ar fi fără sens
$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",
$offset);
?>
În afară de acestea, puteți loga interpelările în interiorul scriptului și în baza de date, dacă aceasta susține acest lucru. Bineînțeles, logarea nu poate preveni atacurile sau încercările de a vătăma baza de date, dar poate fi utilă în depistarea aplicației în care a avut loc incidentul. Log-ul nu este util prin sine, ci prin informația pe care o conține. Mai multă detaliere este de obicei mai bună decât lipsa detaliilor.