Securitatea aplicatiilor web
PHP este un limbaj de programare usor de inteles si aplicat. Acest fapt a oferit multor programatori incepatori un mediu in care sa creeze aplicatii web vulnerabile fara ca macar sa cunoasca acest lucru.
Am trecut si noi prin aceasta faza a vietii de programator (toti suntem incepatori la un moment dat), asa ca putem da niste sfaturi adunate din propria experienta, care speram ca te vor ajuta in crearea unor aplicatii web mai sigure.
Primii pasi
register_globals
In cazul in care este activata, directiva register_globals transforma orice date transmise prin variabile EGPCS (Environment, GET, POST, Cookie, Server) in variabile globale. Astfel, variabila $_GET['pagina'] va fi disponibila in script si ca $pagina, $_POST['nume'] ca $nume si tot asa. Existenta in script a unor variabile nedeclarate de programator creaza probleme mari de securitate si nu numai.
Incepand cu versiunea 5.3.0 a PHP, aceasta setare nu mai beneficiaza de suport, iar majoritatea serverelor moderne o au deja dezactivata. Totusi din motive de compatibilitate cu versiunile mai vechi, este bine sa te asiguri ca aceasta optiune este dezactivata. Acest lucru poate fi facut prin introducerea in .htaccess a urmatoarei linii de cod: register_globals Off (nu toate serverele suporta modificarea anumitor directive PHP prin .htaccess).
magic_quotes
In cazul in care este activata, aceasta directiva va comenta cu \ caracterele de tip NULL, ", ', \ din orice continut extern primit de scriptul PHP. Scopul ei a fost securizarea impotriva injectiilor SQL, multi programatori incepatori nefiind constienti de vulnerabilitatile la care isi expuneau aplicatiile web care transmiteau bazei de date input nefiltrat primit de la utilizator. Cu timpul insa, maturizarea comunitatii de programatori PHP si implicit a limbajului, a dus la o constientizare a dezavantajelor oferite de magic_quotes si la dezactivarea implicita a acestei setari.
Incepand cu PHP 5.3.0 aceasta setare este considerata "invechita" si nu mai beneficiaza de suport. Pentru a fi sigur ca ai dezactivata aceasta directiva, introduce urmatoarea linie de cod in .htaccess : magic_quotes Off (nu toate serverele suporta modificarea anumitor directive PHP prin .htaccess).
display_errors
Pe parcursul dezvoltarii unei aplicatii web, afisarea erorilor este o metoda buna pentru identificarea problemelor. Insa atunci cand aplicatia este disponibila publicului, orice eroare afisata va putea oferi unui potential hacker informatii despre structura aplicatiei, care astfel va deveni mai vulnerabila.
Dezactivarea acestei directive se poate face in .htaccess prin display_errors Off.
Nu te increde in nici un continut extern
Majoritatea aplicatiilor web folosesc intr-un fel sau altul continut extern, fie ca acesta provine de la utilizatori (prin intermediul variabilelor $_GET, $_POST, etc), fie de la alte servere (informatii oferite de anumite servere prin intermediul unor interfete de programare - API). Acest lucru ofera o poarta de intrare in script si de manipulare a acestuia, in cazul in care acest continut extern nu este verificat / filtrat asa cum trebuie.
Orice utilizator al unui site care contine un formular (sau mai multe), poate vedea denumirile elementelor variabilelor pe care scriptul le va manipula (atributul 'name' al campurilor formularului), metoda de transmitere a acestora (atributul 'method' al formularului) si calea catre scriptul care le va prelucra (atributul 'action' al formularului). In felul acesta, un utilizator rau intentionat va putea trimite orice continut catre scriptul tau folosind denumirile si metoda de transmitere a campurilor (printr-un formular sau printr-o cerere HTTP transmisa serverului).
Verificarea datelor externe
De cele mai multe ori, este cunoscut inca de la inceput tipul de date al continutului extern care urmeaza sa intre in script. Verificarea conformitatii datelor transmise de utilizator/server cu tipul de date asteptat, reduce riscul patruderii de continut in format incorect in script.
Putem exemplifica prin campul 'varsta' dintr-un formular de inscriere intr-un magazin online care comercializeaza bauturi alcoolice. Stim ca varsta trebuie sa fie un numar intreg, nu mai mare de 90 (sa zicem) si nu mai mic de 18 - varsta minima pentru a deveni un eventual client al magazinului. Desi putem limita varstele dintre care un utilizator poate alege, prin folosirea unui camp de tip <select>, acest lucru nu garanteaza nimic din punct de vedere al securitatii.
Daca scriptul nu va verifica varsta transmisa si conformitatea ei cu tipul dorit (doar un numar intre 18 si 90 de ani), scriptul va prelucra o informatie incorecta, lucru care poate crea probleme de tot felul (ex: probleme legale in cazul vanzarii de produse alcoolice persoanelor sub 18 ani).
In cazul aplicatiilor care afiseaza o anumita pagina in functie de o variabila de tip $_GET nevalidata, probleme pot fi mult mai grave. Sa zicem ca site-ul functioneaza pe urmatoarea arhitectura: un fisier index.php care va incarca paginile site-ului in functie de variabila $_GET['pagina'] folosind include($_GET['pagina']);.
Daca variabila nu este verificata, un utilizator rau intentionat va putea cere in browser un fisier sensibil (cum ar fi cel cu parole) iar acesta va fi inclus in index.php si afisat. In acest caz, cea mai simpla solutie este validarerea variabilei $_GET['pagina'] contra unei liste care contine caile catre fisierele care se doresc a fi accesibile publicului.
Lucrul cu bazele de date
Folosirea continutul extern in interogari MySQL impune o atentie sporita asupra aspectului securitatii, avand in vedere ca informatiile stocate in baza de date sunt de cele mai multe ori sensibile. Singura solutie care trebuie luata in calcul este folosirea functiei mysql_real_escape_string() al carei unic scop este securizarea impotriva injectiilor SQL.
Exemplul dat de php.net pe pagina functiei este extrem de relevant si concludent. Astfel, in cazul unui sistem de autentificare pe baza unui user si a unei parole, se foloseste urmatoarea interogare: SELECT * FROM users WHERE user='".$_POST['username']."' AND password='".$_POST['password']."'.
Daca datele transmise de utilizator nu sunt verificate si comentate cum se cuvine, se poate ajunge la urmatoarea situatie: in campul 'username' utilizatorul introduce 'cristi', iar in campul 'parola', urmatorul string: ' OR ''=' interogarea rezultata ar fi: SELECT * FROM users WHERE user='cristi' AND password='' OR ''=''. In felul acesta, utilizatorul poate manipula fara probleme interogarea, autentificandu-se fara introducerea unei parole valide.
Daca interogarea va fi facuta folosind mysql_real_escape_string(): SELECT * FROM users WHERE user='".mysql_real_escape_string($_POST['username'])."' AND password='".mysql_real_escape_string($_POST['password'])."', interogarea finala va fi: SELECT * FROM users WHERE user='cristi' AND password='\' OR \'\'=\''.
Protejarea impotriva atacurilor de tip XSS
Un alt punct important care trebuie bifat in procesul de securizare a unei aplicatii web, este comentarea oricarei date externe care va fi afisata pe site.
Un exemplu ar fi o aplicatie web de tip comunitate, in care toti utilizatorii isi pot completa un profil. Un utilizator rau voitor, poate introduce in anumite campuri ale profilului sau cod javascript prin care sa redirectioneze vizitatorii profilului sai catre alte site-uri. Acesta este doar un exemplu, posibilitatile fiind nelimitate. De aceea orice continut extern care va fi afisat trebuie sa fie comentat inainte, preferabil cu functia htmlspecialchars() care va transforma orice caracter specific limbajului html ( <, >, ", ', & ) in entitatea sa corespondenta (<, >, ", ', &).
Mai exista si alte solutii pentru anumite probleme ce tin de securitatea unei aplicatii web, cum ar fi evitarea folosirii extensiilor de alt tip decat .php pentru fisiere ce contin cod php (in mod normal serverul va transmite continutul acelor fisiere ca text) sau protejarea la vizualizare a continutului directoarelor.
Speram ca acest articol iti va fi util intr-un fel, iar daca ai vreo adaugare, completare sau corectare, ne poti scrie folosind formularul din dreapta.