6 tipp, a biztonságosabb php programozáshoz

Általános jó tanácsként: Ne bízzunk meg a felhasználótól kapott adatokban. Minden olyan érték ami a felhasználótól jött gyanús, és csak megfelelő szűrések, átalakítások után kerülhet elmentésre az adatbázisban, megjelenítésre a weblapon.

  • mysql_real_escape_string Kifejezetten fontos funkció. Az SQL injection támadások elkerülésében segít, kirakja a szükséges \ jeleket a felhasználó által beküldött adatokban. Használatához először csatlakozni kell a kívánt adatbázishoz.
  • addslashes() hasonló mint a mysql_real_escape_string, de csak és kizárólag a ” és a ‘ jeleket figyeli. Figyeljünk oda hogy a magic_quotes on beállítás esetén a függvénynek érdekes mellékhatásai vannak.
  • htmlentities() A felhasználótól érkező adatot szűri, a speciális karaktereket kicseréli a HTML megfelelőjére, így az SQL inject és az XSS típusú támadások ellen véd. Akkor használjuk, ha egy felhasználó által bevitt szöveget akarunk megjeleníteni a weblapunkon.
  • strip_tags() A felhasználó által bevitt szövegből kiszedi a PHP, HTML és javascript tag-eket
  • Md5() A jelszavakból képzett 32 karakteres hash-ek tárolása az adatbázisban sokkal biztonságosabb, mintha csak szövegként elmentenénk a jelszót.
  • SHA1()Hasonló az MD5-höz, csak 40 karakteres hash-t képez.

20 HOZZÁSZÓLÁS

  1. a htmlentities() nekem mindig elrontotta az ékezeteket, helyette htmlspecialchars()-t használok

  2. Szasztok!

    Ha biztonságnál járunk, akkor annyi segítsem lenne még, hogy az MD5() vagy az SHA1() helyett ajánlominkább az MHASH-t. (persze, ha a szerveren megtalálható ez a modul)
    Miért is?:
    Mert az MD5-t már pár éve fel lehet törni, és egy Online SHA1 “törőbe” meg kb fél éve bukkantam rá… és tényleg működött :S

    Ezért én átálltam erre. Legalábbis ilyennel még nem találkoztam.
    Speciel én a MHASH_SHA256 -t használom a kódoláshoz, de lehet mást is.

    Dokumentáció és néhány használati tanács:
    http://hu.php.net/mhash
    http://mhash.sourceforge.net/
    http://www.szabilinux.hu/php/ref.mhash.html

    Üdv Dani

  3. Az egyetlen probléma az mhash-al hogy külön modulként kell telepiteni ami a php4 -es szervereken nem volt jellemző a php 5.1.2 óta pedig van HASH függvény könyvtár gyárilag ami hasonló céllal készült.

    Az Md5 decompliler pedig akkor ér valamit ha simát md5(‘password’) -öt használsz. Nállunk egyszerü de nagyszerü módszerként bevált hogy md5(‘user’ . ‘password’) -ot használunk, ezáltal bármilyen md5 / sha1 decompliller táblázat garantáltan használhatatlanná vált, hiszenn minden hash -t egyedeileg kellene végig törni ami azért rengeteg idő. Cserébe igaz kicsit strapásabb a user név váltást megcsinálni, de ezt úgy sem szokták engedélyezni :)

  4. Megjobb megoldas az ugynevezett SALT hozzaadasa. SALT=só, “megsózás/megfűszerezés”. A *nix rendszerek mar az osidok ota hasznaljak a password-ok tarolasanal. Lenyege kb annyi, hogy a “szoveg” egy kis reszet hasznaljak fel az elkodolas soran. Pl: “sziasztok” szovegnel a SALT az utolso 3 karakter, tehat “tok”. Amit te csinalsz TLoF az a felig-jo megoldas csak, lenyegeben te is SALT-ot hasznalt, ami itt esetunkben a “usernev” akar lenni, de ezzel az a baj, hogy ugye fix. Emberunk ugy fog nekiallni a törésnek, hogy tudja mi a usernev es ahhoz keresi a jelszot. A rendes SALT-nál a jelszót kellene tudnia, hogy tudja mi a SALT értéke :) A SALT-nak egyébként nem kell feltétlenül a jelszóból jönnie, lehet véletlenül generált is, csak ekkor ezt külön le kell tárolni a jelszóhash mellé, hogy az ellenőrzésnél meglegyen :)

    Persze amit mondasz az szentigaz, márhogy akár a username hozzáadása a hashgeneráláshoz elegendő, hogy ezek a “szivarvanytablak” ertelmuket vesszék :)

  5. A SALT szerintem biztonságosabbá tehető, ha már eleve egy hash-t kódolunk tovább. Igaz ez a későbbi felhasználói adatmódosításoknál okozhat kisebb kellemetlenséget (pl: a jelszót meg kell adni a módosításhoz; regisztrációkor, belépéskor, adatmódosításkor nagyobb szerver terhelés), cserébe viszont szinte teljesen értelmezhetetlen a visszafejtett kód.
    Az érthetőség kedvéért itt egy lehetséges megoldás (a szakdogámnak szánt weblapon is ezt alkalmaztam :D):
    $sql_pass = sha1($nev . $mail);
    $sql_pass = md5($jelszo . $sql_pass); (a $jelszo a valós jelszó ascii 2-vel eltolt változata, tehát az a betű c-ként szerepel, és így tovább)
    Mivel belépéskor úgyis kell az sql adatbázisban turkálni, így nem nehéz a mail-t kikeresni az azonosításhoz. Ezt természetesen még úgy is lehet bonyolítani (értékes szerveridőt elpazarolva), hogy magát a jelszót az sha1-es hash-be belekeverjük valamilyen függvény segítségével, majd ezt kódoljuk (habár az így kapott karaktersorozatot már szinte felesleges mégegyszer kódolni :)).

  6. Thomas: Azt hiszem félreértettél: én nem a usernev mint string hanem mint a $usernev mint a változót használom elkódolásra. Ezért minden egyes jelszóhoz egyedi salt kerül.

  7. Látod Tlof, ha bejártál volna az óráimra, akkor pár hibával kevesebb lenne a fentiben. :P

    addsalshes: itt elég lett volna annyit írni, hogy NE HASZNÁLD! Amúgy meg a függvény escapeli a \ jelet és a NUL karkatert is, és semmilyen mellékhatása sincs magic_quotes esetén, ott az escapelést a PHP automatikusan végiz.

    htmlentities: “így az SQL inject és az XSS típusú támadások ellen véd”, ne már Tlof, régi motorosként ez elég gáz. Ennek a függvények semmi köze nincs az SQL injectionhöz.

    strip_tags: a javascript tag is HTML tag ;). Plusz itt érdemes szintén megjegyezni, hogy ne használd kategória kb. mert csak nagyon alap támadásoktól véd meg. Kb. ez lenne a minimum: http://htmlpurifier.org , de az igazi, ha nem lehet HTML-t megadni (ergó lehet a teljes bementre htmlentitiest) nyomni.

    Üdv,
    Felhő

  8. Hodicska Gergely: “mert csak nagyon alap támadásoktól véd meg” – ezt hogy érted?

    ez valóban elég alap cikkre sikerült, pl a hibakeresésből fakadó résekről is lehetett volna írni(hibajelzések, bennt felejtett echo, var_dump stb.), az erőforrásos műveletek védelméről, magáról a szerver beállításáról(sok weboldalon látom, hogy engedélyezik a könyvtár kilistázását…)

    amúgy pedig http://wfsz.njszt.hu/projektek_biztonsag.php#error oldalon megtalálhatóak az alap védelmi tanácsok

  9. Igen, ez egy alap doksi, ami igyekszik felhivni az emberek figyelmét, hogy kéne ezzel a témakörrel is foglalkozni.

    Ha belenézel a weblabor, vagy a tutorial.hu fórumaiba, és látod, hogy milyen kódokat másolnak be, hogy nézd meg hogy mi a baj, akkor tudod, hogy a legtöbb embernél már az haladás, hogyha nem közvetlenül a $_GET, $_POST -ból illeszti be a query-be az adatokat.

    Elismerem, hogy nem egyetemi szintü ez a post, és hogy tudok ennél sokkal jobbat is, de a bejövő kérdések és a weblap témája alapján erre van igény, és nehéz valakit táncolni tanitani, ha még járni sem tud biztosan.

  10. Azért ez még nem ok arra, hogy tök alap, és tök durva tárgyi tévedések legyenek benne. Az hogy kezdőknek szól, az igazából még nagyobb felelősség, plusz miért jobb egy kezdőnek azt mondani, hogy htmlentites és nem htmlspecialchars, meg hogy véd az sql injection ellen? ;)

    Üdv,
    Felhő

  11. “mert csak nagyon alap támadásoktól véd meg”

    Egyrész már olyan alap dolgokkal át lehet verni, mint a script tagbe ékelt script tag (“<script>”). Másrészt XSS kódot hihetetlenül sok féle módon be lehet tolni egy oldalba, ezek többségétől nem véd meg a strip_tags. Ráadásul bonyolultabb eszközök sem lehetnek ebben biztosak, mert nem csak szabványos megadások ellen kell felkészülniük, hanem az ezerféle böngésző bugok miatt is működő változatoktól. És akkor még vannak olyan nyalánkságok is, mint protocol filtering, sok olyan attributum van, amit megengedsz, de nem csak mondjuk egy URL-t lehet benne feladni, hanem “javascript:xss()” is elfogadott különböző böngészőkben, itt szintén sütheti az ember a strip_tags-et.

    Üdv,
    Felhő

  12. Szerintem sajátot nem érdemes pont azért a téma bonyolultsága miatt. Valószínűleg nem lenne annyi időd, hogy egy igazán korekt megoldást találj ki. Valamint igazából az is érdekes, hogy egy adott megoldásról elmondható-e, hogy tuti biztos, tekintve, hogy böngésző bugokat is figyelmbe kell venni, és ugye ezekről nem mindig tudhatsz, pláne nem eljövendő hibákról.

    Egyik megoldás lehet az, ha valamilyen nem HTML markupot használsz. Ilyenkor a bejövő szövegre kapásból nyomsz egy htmlspecialcharst, majd szépen lecserélgeted a markupot HTML-re, ekkor azonban már pontosan tudod, hogy milyen HTML fog a szövegbe kerülni.

    Egy érdekes megközelítés lehet, ha mégis HTML kell, hogy magára a szövegre egyből nyomsz szintén egy HTML specialcharst, és ebben a szövegben kezdesz el bizonyos mintákat visszacserélgetni HTML-re. Így ha a usered nem trükközött (tehát csak azokat a jelölőket használta, amiket te megengedsz, vagy amire felületet adsz), akkor szépen visszakapod a beírt HTML-t, ami nem veszélyes, viszont ha trükközött, akkor a visszacserélgetés nem fog sikerülni, így a bevitt rosszindulatú HTML sima szövegként fog megjelenni. De ezt azért jól át kell gondolni, hogy nehogy lyukas legyen valahol.

    Üdv,
    Felhő

  13. azért szerintem ez kicsit fura, hogy mindenki mindig közli, hogy figyeljünk a bejővő adatok védelmére, még sincs egy normális szabványosnak tekinthető megoldás. az általad leírtak nyilván működhetnek, de azért kiváncsi vagyok hogy egy ilyen szövegparsolásnak mekkora erőforrásigénye van egy nagyobb szöveg esetén (ha még bele lenne fordítva a c-ben írt kód, akkor még azt mondom oké, de phpban – tapasztalataim alapján – elég lassú a sztringkezelés más nyelvekhez képest).

    úgy tudtam, hogy az 5.2 php óta van egy filter osztály, de egyszerűen nem találtam a manualban. ezzel nem tudjátok mi történt?

  14. köszi, valóban :)

    nem hiszem, mert ha végre írnának egy normális megoldást, akkor azt lehetne használni. nyilván, ha abba kiderül egy bug akkor a fél világ szívni fog, de kevesebb is lenne benne a hiba. na mind1, ez csak egy vélemény…:)

  15. Biztonsági megoldásokban szinte mindig az egyedi megoldások a nyerők. Ha van egy általánosan használt függvény, osztály vagy akármi, annak érdemes nekifeküdni, megkeresni benne valami hiányosságot (minden kódban lesz ilyen), mert általa nagyon sok rendszerhez nyílik kiskapu. Ráadásul a rendszer gazdija nyugodtan ül, hiszen ő “megtett mindent”. Az egyedi védelem (ha legalább olyan sikeresen van megírva, mint a feltételezett általános) egyrészt nehezebben kiismerhető (a cracker nem tud belőle telepíteni egy példányt a gépére, hogy próbálgassa), másrészt kevesebb haszonnal kecsegtet a feltörése. A próbálkozásokat pedig a logból nem olyan nagy feladat kiszűrni.

  16. Nincs feltörhetetlen oldal.
    Mi azon fáradozunk, hogy szép és használható oldalakat fejlesszünk, amik mellesleg biztonságosak is. Ha jól számolom, ez rögtön három dolog amire figyelni kell. Plusz még a határidők.
    Míg aki csak töréssel foglalkozik annak egy dologgal kell törődnie hibakereséssel.
    A legjobb megoldás az ha megtaláljuk az egyensúlyt. Az egyszeri próbálkozó ne törje fel túl könnyen az oldalt, a profik ellen meg csak imával tudsz védekezni. Az ha bent van hiába a LOG azt is kitakarítja maga után.
    Minden baj ellen a legjobb védelem a biztonsági mentés. Ne az oldalt féltsük. Hanem ami az adatbázisában van ha több év munkája és ügyfeleinek adatai elvesznek az nagyobb gáz, mintha újra kell írni egy egész CMS-t.

HOZZÁSZÓLOK A CIKKHEZ

Kérjük, írja be véleményét!
írja be ide nevét