Munca cu bitii

Friday, 17 September, Year 2 d.Tr. | Author: Mircea Popescu

Spre deosebire de munca cu oamenii, munca cu bitii aduce o paleta ingusta de satisfactii profunde (munca cu oamenii aduce o paleta larga de satisfactii superficiale, da' sa trecem).

Oarecari probleme apar atunci cind avem a scrie interfata intre unii si altii. De problemele ocazionate de trecerea dinspre biti inspre oameni am mai vorbit, si-am si ilustrat, cu fiecare succes produs de Polimedia (despre care diversi docti explicau ca n-are nici o sansa ca "designu' nu-i profi" etc, pentru a se vadi mai apoi ca dimpotriva, asta ajuta). In ultima vreme au cam cedat nervos si ori s-au spinzurat ori s-au convertit, asa incit principiile mele cele incorectele si "neprofi" de-acum 2 ani au devenit intre timp trendul central. Aceeasi evolutie ca si-n cazul chestiei cu lungimea articolelor, precum si-a tuturor chestiilor pe care-am pus mina in online.ro. C-asa-i viata asta, grea.

Dimpotriva, problemele ocazionate de trecerea dinspre oameni inspre biti nu tin de aspect, cit de securitate. Prima lectie care se preda la orice scoala de programare este ca "you must sanitize all user provided data whatsoever, no exceptions." Este in limba engleza si nu in limba romana fie pentru ca in limba romana nu se face scoala de programare de-adevaratelea, fie pentru ca scoala care se face nu conteaza, fie pentru ca bozgorii si cu jidanii conspira impotriva noastra, va alegeti singuri ce explicatie va convine. Motivul real este ca in propozitia englezeasca se vorbeste despre html forms, php si mysql, iara nu de chestii generale despre masini programabile si MUX-uri, ca la Poli.

Deci, nu e voie sa introduci nimic obtinut de la utilizatori, absolut nimic, in baza de date fara a "sanitiza" intii chestia. Cum se face asta ? Pai, fie rulezi un regedit si pastrezi doar caracterele permise (chestie care prezinta dezavantajul ca unele caractere sunt permise in unele contexte dar nu si in altele), fie imparti obiectul in bucatele dupa schema la care ar trebui sa-i adere si apoi il reconstruiesti (folosind de exemplu pentru un url parse_url(), validind separat bucatile si recompunind obiectul la final), fie folosesti identificari exacte (daca utilizatorul a spus == "asta" atunci facem asta, daca a spus == "aia" atunci facem aia si in rest nimic).

Fie, daca esti lenes, folosesti un script pre-scris, ceva precum mysql_real_escape_string(). Problema cu mysql_real_escape_string este ca

If magic_quotes_gpc is enabled, first apply stripslashes() to the data. Using this function on data which has already been escaped will escape the data twice.

mysql_real_escape_string() does not escape % and _. These are wildcards in MySQL if combined with LIKE, GRANT, or REVOKE.

Si diverse alte probleme de aceeasi natura. Plus ca

Warning: mysql_escape_string() [function.mysql-real-escape-string]: This function is deprecated; use mysql_real_escape_string() instead

De ce s-a deprecat mysql_escape_string() ? Pai pentru ca nu functiona. Si de ce ii zice "real" escape string la asta noua ? Pai ca cica functioneaza, calumea, de data asta. Oare ?

Eu am, bineinteles, o solutie alternativa, care este de altfel si principiu de programare pentru mine, cu obligativitate de aplicare la mine-n firma. Si anume, tot ce se duce in baza de date venind de la utilizator este fie hash fie base64encode. Simplu si pe inteles (merita citit articolul din wikipedia daca nu stiti ce-i aia, e unul din putinele exemple de articole bine scrise acolo). Daca-i parola sau alte asemenea, atunci hash. Daca nu-i parola si nici alte asemenea, atunci base64.

In acest mod simplu avem garantia ca:

  • Toate caracterele, in toate limbile si toate caracterele speciale, in toate formatele, sunt salvate corect si pastrate indiferent in toate bazele de date, si pot fi mutate din una in alta fara nici un fel de riscuri, indiferent de considerente precum schema scl.
  • De asemenea bazele de date pot fi comunicate in conditii de siguranta peste absolut orice legaturi functionale, fara verificari necesare de compatibilitate.
  • Baza de date poate tine, fara nici un fel de riscuri, orice succesiuni de caractere, inclusiv combinatii dureroase precum '-- ; " OR 1 pe care alte sisteme ori le sterg ori sucomba.
  • Nu exista nici un fel de riscuri si nu sunt necesare nici un fel de verificari de securitate pentru a sanitiza datele originate de la utilizatori, ceea ce reduce semnificativ costurile cu scrierea si mentinerea codului.

Da, este adevarat ca acest sistem are dezavantajul de-a adauga 33% la lungimea oricaror date, si nu este neaparat o solutie buna pentru sisteme foarte mari (si anume, sisteme pentru care costul unei cresteri cu 33% a volumului datelor primite de la utilizatori depaseste costul unor programatori competenti care sa asigure codul). In practica, acest dezavantaj conteaza mai rar, din motive stufoase in care nu vom intra aici.

Avantajele in schimb, in ce priveste siguranta, portabilitatea codului si portabilitatea datelor sparie mintea.

Nu-i nevoie sa-mi multumiti. Spor.

Category: 3 ani experienta
Comments feed : RSS 2.0. Leave your own comment below, or send a trackback.

26 Responses

  1. Mda, dar, spre exemplu, cand vrei sa cauti prin acea baza de date? Dai un select in base64? :)

  2. Mircea Popescu`s avatar
    2
    Mircea Popescu 
    Friday, 17 September 2010

    Care-i problema ? Doar e transparent.

  3. Pai este transparent, dar ai niste limitari, daca inteleg eu bine schema:
    - nu poti sa faci cautari genul LIKE %whatever%
    - nu poti sa cauti dupa data din sql, daca encodezi si data
    - perfomanta nu va fi prea buna deoarece nu poti sa folosesti indecsi

    Si in plus, asta nu-ti rezolva toate problemele. Daca sa zicem ca aplicatia e una web, un user ar putea sa bage niste cod javascript in baza de date, care ulterior e posibil sa fie executat de useri, deci oricum mai trebuie sa bagi o gramada de sanitizari, pe langa care sql injection este una dintre cele mai simple de rezolvat.

    E o solutie, dar mi se pare prea inflexibila ca sa fie practica si nu cred ca merita dezavantajele doar pentru a te apara de sql injection. Sa zicem ca ai o aplicatie micuta, pentru care solutia asta functioneaza, dar cu timpul, aplicatia devine mai maricica. Ar trebui sa o modifici si sa o securizezi prin solutia clasica. Sau cazul in care aplicatia e pe interneti, deja se presupune ca tre sa poata sa intre milioane de oameni pe ea ca sa ai sansa de a face un ban de-o ciunga.

  4. Mircea Popescu`s avatar
    4
    Mircea Popescu 
    Friday, 17 September 2010

    E adevarat ca nu poti face LIKE %%, da' pe de alta parte hai sa fim seriosi, nici nu vrei sa faci asa ceva. Sau cu alte cuvinte, daca vrei sa faci asa ceva e o dovada ca ti-ai facut prost planificarea si tre' sa reconstruiesti oricum.

    Data nefiind introdusa de utilizator, ci de MySQL nu intra in discutie.

    Clar ca poti folosi indecsi, de ce sa nu poti ?

    Dimpotriva, sanitizarea contra injectiilor de html/js se rezolva foarte usor, distrugind < la output (un alt aspect al programarii care nu-i indeobste bine tratat de mai nimeni, inclusiv de wordpress. Nu-i corect sa cureti tagurile la INTRARE, e corect sa inlocui < cu &lt ; la IESIRE.

    Acu tie ti s-o fi parind cum doresti sa ti se para, da io-ti spun din experienta ca nu-i, ci chiar dimpotriva. Si nu, faptul ca aplicatia e pe internet nu presupune ce presupui tu. Cind zic

    si anume, sisteme pentru care costul unei cresteri cu 33% a volumului datelor primite de la utilizatori depaseste costul unor programatori competenti care sa asigure codul

    ma refer la chestii semnificativ mai complexe decit orice exista pe internet.ro la ora actuala (absolut orice).

  5. Pai nu inteleg cum poti sa folosesti indecsi si cautari si alte minuni de baze de date cand tu ai in tabele niste hashuri. Cum faci sa-mi gasesti toti userii al caror nume contine Gigel si care s-au nascut intre 3 ian 1970 si 21 dec 2012?

    Eu ma gandesc ca ar trebui sa scoti tot tabelul din baza de date, il bagi in memorie, faci base64 decode la tot si apoi cauti, dar asta e cam ineficient, nu?

  6. Mircea Popescu`s avatar
    6
    Mircea Popescu 
    Friday, 17 September 2010

    Deci tocmai am descoperit un bizar bug in wordpress. Exista in textul comentariului un </blockquote> inainte de ultimul paragraf, dar in html n-ajunge.

  7. Mircea Popescu`s avatar
    7
    Mircea Popescu 
    Friday, 17 September 2010

    @Gheorghe Nu. "Select from table where nume =". base64_encode ("Gigel") && < DATE < etc.

  8. Pai da, dar am zis contine, ori daca ai fi avut un user Gigelina, ai fi ratat-o, si cu data tot nu am inteles. Ca sa poti cauta dupa date din baza de date, ar trebui sa ai o coloana de tip date, datetime, etc. care nu poate stoca hashuri base64 :)

  9. Mircea Popescu`s avatar
    9
    Mircea Popescu 
    Friday, 17 September 2010

    Tu esti turc ? Ia vezi ca raspunsuri la aste doo nelamuriri se gasesc deja date in #4.

    Daca tu intrebi ceva si io-ti raspund nu poti continua tot pe ideea ta, ca de-aia ti-am raspuns, sa te lamuresc.

  10. Da, scuze, mi-a scapat aia cu data. Data e introdusa de mysql doar in cazuri simpliste in care iei doar data curenta sau ceva, daca iei data dintr-un formular, este introdusa de user, si deci poate fi introdus un sql inject pe-acolo.

  11. Mircea Popescu`s avatar
    11
    Mircea Popescu 
    Friday, 17 September 2010

    E, eu inca n-am pomenit de caz concret in care sa trebuiasca sa-ti introduca userul data cu minutele lui. Tu cind ai introdus ultima oara o data intr-un formular pe web ?

  12. Cand imi cere yahoo data de nastere sa vada daca sunt sau nu minor spre ex.

  13. Mircea Popescu`s avatar
    13
    Mircea Popescu 
    Friday, 17 September 2010

    Eu prefer sa rezolv chestia aia printr-un clickbox, "I was born on or before 16th of September 1992". E o solutie mai buna din punctul de vedere al uzabilitatii, si incet incet incepe sa fie tot mai folosita.

    Alt exemplu ?

  14. Asta da, dar nu poti sa te limitezi la asa ceva. Daca faci urmatorul facebook si vrei sa stii cati ani au luserii, sa stii daca sa le vinzi sex toys sau scutece pentru batrani. Sau faci aplicatii care gestioneaza identitati de persoane, date de expirare ale cardurilor, si o gramada de alte chestii.

  15. Mircea Popescu`s avatar
    15
    Mircea Popescu 
    Friday, 17 September 2010

    O gramada de chestii teoretice.

    In practica ramane cum iti zic.

  16. Haha, ok, daca tu zici ca n-o sa faci vreodata o aplicatie in care ceri o data unui user, te cred pe cuvant. Ideea e ca, nu mai suntem in anii 90, orice programator cu o oarecare bruma de competenta stie cum sa se apere de sql inject.

    Problema cea mai mare acum e in browsere, javascripturi, etc. E atat de complex incat nici cineva care cerceteaza non-stop vulnerabilitati in aplicatii web nu poate sa scrie cod 100% secure. Poate sa scrie din greseala cod cu vulnerabilitati bine cunoscute de el fara sa-si dea seama. Nu exista inca solutii absolute, un sistem infailibil de a scrie cod, deci din punctul asta de vedere, nu poti inlocui competenta unui programator. Macar unul sa ai mai rasarit, daca chiar te intereseaza subiectul securitatii.

  17. Mircea Popescu`s avatar
    17
    Mircea Popescu 
    Friday, 17 September 2010

    Mda.

    Problema principala as zice c-o constituie pustii care dau din ei adevaruri universale pe baza chestiilor pe care le-au mai citit saptamana trecuta pe net, daca ma-ntelegi.

  18. Semne bune anul are. In curind vedem si polimedia in IE. Se lucreaza.

  19. Parca marianul nu mai trecea pe aici?

    In alta ordine de idei, data o poti construi din diverse dropdown boxuri sau si dac-o introduce omul cu manurile lui poti sa faci o verificare cu php inainte de a o baga in DB, si-i bistos treaba. Injectii sql in asa ceva inca n-am vazut.

  20. Mircea Popescu`s avatar
    20
    Mircea Popescu 
    Saturday, 18 September 2010

    Aia e compunerea dupa structura de care vorbeam.

    Normal ca verifici, dar ai la dispozitie isnumeric() ceea ce te ajuta mult. Da' de verificat tre' sa verifici, ca si dropdownu-i numa' un form, n-are securitate.

  21. Tu prin schema asta ti-ai redus capacitatea de a face cautari prin baza de date, si pentru ce? Ca sa eviti probabil cea mai bine cunoscuta si cea mai bine documentata vulnerabilitate din toate timpurile. Ca aia care-au facut php-ul au fost idioti si n-au fost in stare sa faca o functie care escape-uieste niste caractere, asta e partea a doua, iar magic quotes a fost o idee stupida de la inceput. Daca n-ai incredere in competenta lor, fa-ti tu o functie, citeste codul sursa al parserului sql al lui mysql, sa fii sigur ca nu ascund developerii un caracter special ca backdoor sau ceva, etc.

    Sau hai inca 2 alternative: parametrized queries si proceduri stocate. Cred ca daca nu te deranjeaza sa ai 2/3 din baza de date hashuri base64 nu te deranjeaza nici sa tii codul sql in proceduri stocate.

  22. Mircea Popescu`s avatar
    22
    Mircea Popescu 
    Monday, 20 September 2010

    Inca o data mei, base64 nu reduce nimic deloc nicicum. Ca ti-e tie inconfortabil mental nu inseamna ca e inconfortabil masinii, din punctul ei de vedere nu exista nici un fel de problema, absolut, deloc. Acest text e la fel de descifrabil sau indescifrabil, procesabil sau neprocesabil pentru masina cum este si echivalentul lui in base64, cum este si echivalentul lui scris in baza 34, cum este si orice alt echivalent numeric.

    Motivul principal pentru care te-am tratat dismisiv la #17 este tocmai acest soi de privire subiectiva asupra aparatului, care denota in principiu o slaba culturalizare la nivelul fundamental. Calculatorul nu-i calul tau credincios din povestile cu Vestul Salbatic, calculatorul e o simpla si banala masina de calcul numerica.

    Alternativele din final se adreseaza altui nivel de programare. Eu discut aici de nevoile teoretice ale programatorilor de ordinul sutelor, nu miilor de dolari pe ora.

    Trecind peste astea, faptul ca-i cea mai bine documentata vulnerabilitate din toate timpurile nu spune neaparat ceva despre cit de usor de evitat este ea, cum pari sa sugerezi tu. Mariajul e si el cea mai bine documentata alegere gresita din toate timpurile, si cui serveste documentarea asta ?

    In fine, abordarea reductionista (cind afirmi ca eu fac X pentru Y, desi eu ti-am spus de 2 ori deja ca-i pentru Y, Z si K) dovedeste ca nu citesti cu prea multa atentie, sau daca nu, ca citesti pentru a-ti confirma presupozitiile mai degraba decit pentru a te informa.

    Ambele aceste doua defecte te descalifica de la a fi luat in serios, chiar daca altminteri tu probabil ai merita sa fii.

  23. Tot ce zic eu e ca lui mysql ii este incomfortabil sa caute text in hashuri base64. Atat am avut de zis, poti sa pui asta la dezavantaje :)

  24. Mircea Popescu`s avatar
    24
    Mircea Popescu 
    Monday, 20 September 2010

    base64 nu este un hash. Ca sa nu mai mentionez ca principala utilitate a unui hash este sa reduca timpii de cautare prin tabele, fie ele mysql sau altceva.

    Pune mina pe o carte. Pe bune, si spre binele tau iti zic.

  25. Ok, solutia ta e perfecta, ar trebui sa o bage default in toate enginurile de baze de date.

  26. Mircea Popescu`s avatar
    26
    Mircea Popescu 
    Monday, 20 September 2010

    Lmao aia ne-ar mai lipsi.

Add your cents! »
    If this is your first comment, it will wait to be approved. This usually takes a few hours. Subsequent comments are not delayed.