ID-uri numerice curate in PHP

Adesea m-am lovit de problema sanitizarii variabilelor care provin din input, si nu zic asta facand referire la PHP, ci la programare in general. Din moment ce am avut boala sa studiez catusi de cat bazele securitatii, mi-a ramas in cap un principiu foarte bine formulat: “all user input is evil!”. Adevarat grait. Deci am inceput sa gandesc aplicatiile dupa metoda user proof. In primul rand cand testez ceva nou, nu testez dupa cum ar trebui sa fie utilizata aplicatia in mod corect, ci cum NU ar trebui sa fie folosita, si ce sa se intample in acele cazuri. In primul rand pentru ca o aplicatie nu este o chestie democratica unde userul face ce vrea el si adesea face prost. Deasemenea intervine si cealata extrema. Unde nu este prostie – este viclenie – deci se poate trezi cate un h4x0r de asta cu mai mult timp liber la dispozitie sa te caute la oo (a se citi: securizare).

Problema ID-urilor numerice in PHP desi este una destul de banala, rezolvarea este multipla. De-alungul timpului am testat mai multe chestii, dar doar recent am ajuns la o forma finala care sa ma multumeasca deplin. De ce ID-uri numerice? Pentru ca este foarte usor de lucrat cu ele cand se interactioneaza cu o baza de date. Orice tabela care trebuie sa stocheze in mod unic niste chestii, are o cheie primara. Pana acum cea mai desteapta chestie in materie de chei primare este cheia intreaga care se seteaza cu auto-increment – ceea ce asigura complet unicitatea datelor. Recomandarea ar fi ca auto incrementul sa inceapa de la 0 (chestia asta o sa se lege de ce o sa zic mai jos). Bonus ar fi faptul ca fiecare tabela de acest gen ar trebui sa aiba cheia primara indexata pentru a reduce considerabil timpul de cautare al ei.

Adesea aceste chei primare din baza de date sunt trimise prin intermediul requesturilor de tip GET, deci se vor regasi in componenta URL-ului. Problema se pune atunci cand pe langa acel ID numeric, utilizatorul (in mod intentionat) introduce si altceva pe langa acel ID. Treaba poate sa se imputa de la XSS (Cross Site Scripting) – atunci cand acea cheie se regaseste in pagina, sau la atacuri de tip SQL injection (mai grav).

Desi exista functii native in suportul de MySQL pentru PHP, acestea sunt destul de triste la ID-uri numerice, deci am preferat propria metoda:

function clean_id($id)
{
$id=preg_replace("@[^0-9]@", "", $id);
if (empty($id))
	$id=0;
return $id;
}

Chestia asta de mai sus face vreo doua chestii … prima este aceea ca da strip la tot inputul care nu e numeric. A doua verifica ce a mai ramas, iar daca are valoarea 0 (orice 0 din PHP), atunci returneaza un 0 numeric. Este important acest zero numeric … ziceam ceva mai sus de el … acest zero numeric are grija ca interogarea sa nu dea de o chestie gen <<WHERE id=”>> si sa bubuie o eroare de SQL (care in anumite cazuri … ar putea la randul ei sa divulge alte chestii).

Actualizare:

Datorita observatiei lui AgLiAn am ajuns la concluzia ca functia mea initiala nu rezolva o problema: interger overflow, chestie ce mai departe se traduce in interpretarea ca float de catre PHP – si de unde pot aparea alte probleme. Si pentru ca am mentionat pe undeva mai sus de auto-increment (si acest obicei nu o sa se transforme peste noapte pana la proba contrara ce demonstreaza un obicei prost), functia clean_id(); devine:

function clean_id($id)
{
return abs(intval($id));
}

De ce USER si NU admin

Probabil ca este una din intrebarile care fiecare utilizator Windows ar trebui sa si-o puna. Incepand cu Windows NT, sistemul de operare al celor de la Microsoft a inceput sa implementeze o bruma de sistem de operare multi-user, deci implicit au aparut privilegiile pentru ca utilizatorii sa nu se mai plimbe de colo-colo si sa faca FUBAR sistemul. Pentru home use, incepand cu Windows XP SP2, Microsoft a inceput sa ofere in sfarsit ceea ce se doreste de la un asemenea sistem, chiar daca pe alocuri lasa de dorit.

Si totusi de ce USER? Simplu … pe vremea cand aveam vechea lista de messenger se intampla destul de des sa bornaie careva ca iar i-a fost virusat “pisiul”. Evident, lucrand in marea majoritate a timpului sub OS X sau ubuntu, mi se cam rupea de chestiile astea pentru ca nu ma loveam de astfel de probleme. Nu pentru ca sistemele respective nu ar fi virusabile, ci pentru ca nu sunt virusabile in mod implicit. Trebuie sa o faci cu intentie sau sa faci parte din clasa populatiei care este imbucurator de proasta. Pacatul Microsoft este faptul ca in mod implicit un sistem proaspat instalat da pe mana utilizatorului un cont cu drepturi de administrator. Marea masa a utilizatorilor s-au obisnuit cu ideea de a face ce le trece prin bostan chiar daca asta nu inseamna ca fac neaparat si bine, si Doamne fereste, nu ar depune eforturi intelectuale pentru remedierea situatiei. Gravitatea provine din faptul ca un virus rulat din “admin” se va instala ca “admin”, deci are acces deplin la anumite resurse care ar trebui sa fie protejate, si fara de care ar fi o simpla chestie inutila care nu ar “virusa” nimic. Si asa ajungem la aia care bornaiau mai sus ca au fost virusati.
Continue reading