![]() |
|
||||||
|
|
| 29.07.10 / 21:53 |
|
Martin Rebane
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.Failide avamine Failide avamisega PHP's tuleb olla väga ettevaatlik. Ja sellel alal tehakse pahatihti vigu(ka paljud "veebifirmade" tehtud lehed kannatavad selle haiguse all). PHP kood:
Nõnda saab avada ainult switch tsüklis defineeritud faile. PS! See ei puuduta ainult include()'t, vaid ka require(), fopen() jmt funktsioone. Ära kasuta skriptide includemiseks mõeldud funktsioone URL'ide avamiseks, kui sa pole 101% kindel, et seda muutujat keegi muuta ei saa. PHP kood:
Tore skriptike on see niikaua, kuni $url='http://www.neti.ee'; või $url='http://www.php.ee';. Aga hoolitse selle eest, et sinna $url muutujasse ei satuks: $url='http://www.pahalane.ee/v2ga_kuri_skript.txt';, mis näituseks otsustab su veebiserveri failidest tühjendada. MySql ja muutujad Teine turvaauk, mida esineb ka paljudes, isegi hirmuäratavalt paljudes programmides, on see, et MySqlile söödetakse sisse kontrollimata muutujad. Üks asi, mis on kohustuslik, on mysql käsus jutumärkide kasutamine: Sest kui nimi juhtub olema kasutaja sisestatav muutuja, siis asi see tal oma nimeks kirjutada: kala or admin=1 Mille tulemuse tekib query: Ehk valitakse ka kõik administraatorite andmed ja need siis kasutajale kuvatakse(loodetavasti keegi tänapäeval siiski passworde tekstina ei hoia, selline asi oleks küll lihtne ja mugav, aga mingi imepisike näpukas kuskil hoopis teises skriptiotsas võib selle saatuslikuks turvaauguks muuta). Ja sellisel juhul ei mängi mingit rolli see, kas addslashes() on kasutuses või mitte. Läbi läheb selline auk igal juhul. Addslashes() on sinu sõber! Tõsi, tänapäeval on serveri administraatorid, kes vähegi turvalisusest hoolivad, keeranud php konfist peale kõiksugu toredad võimalused kasutaja käest tulnud muutujates igasuguste ohtlike märkide taandamiseks . Nt sa küll kasutad jutumärke, aga kui ohtlikud märgid(nt jutumärgid ise) taandatud ei ole, siis liidame kokku eeltoodud näites kasutatud query ja sellise stringi: kala" and admin="1 ...mis teeb kokku: $sql='select * from users where nimi="kala" or admin="1"'; (terve tabeli fetchimiseks tuleks kirjutada nt or 1=1) Simpel, huh? Näituseks insert query korral pole sugugi võimatu välja mõelda, kuidas ennast, juhul kui eksisteerib väli 'admin', administraatoriks muuta. Või kui tõesti ei suuda välja mõelda, siis sisselogimisel võib enda kasutajanimeks seada hoopis: "kala' #", mis passwordi kysimise osa üldse välja kommenteerib.. Aga ma kasutan ju jutumärke ja php.ini on ka niimoodi paika krutitud, et kogu kasutaja käest tulnud info ära töödeldakse! Järelikult sul ei ole vaja addslashes pärast üldse muretseda ja võid selle funktsiooni ära unustada... oot! Aga siiski, oletame, et sul on query: ...ning Kõik oleks nagu korras. Asi läheb korralikult läbi, mingit kasutaja poolt sissesuditud "or" klauslit mysql ei täida. Aga natuke hiljem võtad sa selle sama asja kuskil teises skriptiotsas lahti: ning pahaaimamatult kasutad sealt saadud tulemusi uue query koostamiseks. Loomulikult ei kasuta sa addslashes() funktsiooni, kuna tegu ei ole kasutajalt saadud infoga ning mingit ohtu karta pole. Ja sellel samal põhjusel ei taanda ka PHP neid muutujaid ära. Aga sinu ohutu query ei küsi andmebaasist mitte sinu oodatud: select * from users where username="mingi ohtutu kasutajanimi"; Vaid kasutajale meelepärase: select * from users where username="kala" or id="2"; Pahalane sai oma tahtmise, seekord suht süütukese, aga oletame, et tegemist on nüüd hoopis passwordi muutmise skriptiga ning kasutajanimeks ei oleks mitte kala" or id="2, vaid kala" or username="adminni_nimi_siia... Järeldused tehku igaüks ise. Muutujate tüübid Kui sul on teada, et muutuja peab olema numbriline, siis alati veendu selles. Üks pluss on see, et sa saad kindel olla muutuja õiges sisus ning teine asi see, et soovi korral saad vale sisu avastamisel alati pahalase andmed logida ning nt kiirelt omale emaili saata. Kuidas siis muutujatüüpe kindlaks teha? Näiteks on sul ilus ja kena number(või sa vähemasti arvad, et peab olema) muutujas $id, siis et selles ikka kindel olla, lased ta läbi sellisest masinast: Kui tahad määrata ka else klauslit juhuks, kui tegu ei ole õige asjaga(int kasutamine tagastab stringi korral '0', mitte ei anna veateadet), siis uuri funktsioone is_int(), is_bool(), is_integer(), is_numeric(), is_string(), is_array(), is_object() ja is_float(). Hoolitse selle eest, et muutujad tuleksid õigest kohast! Kui muutujad on ette nähtud formist tulema, siis ära kasuta kuju: $muutuja vaid $_POST['muutuja'] Kui form postitatakse get meetodiga, siis $_GET['muutuja'], täpselt samuti ka kõigi teiste muutujatega: URLi realt tulnud muutujad on samuti: $_GET['muutuja'] sessioonimuutujad: $_SESSION['muutuja'] cookiemuutujad: $_COOKIE['muutuja'] Kasutades $_**** perekonda saab koodi ka igale serverile porditavaks(on servereid, kus register_globals on maha keeratud - kood peab ka seal töötama!). Ka on globaalsete muutujate kasutamine PHP programmeerimiskeele arendajate poolt taunitud. Siiski, 100% ei saa ka seda moodust usaldada, kuna tõsine tegija saadab soovi korral $_POST/GET/jmt muutujad ise, kasvõi lihtlabaselt telneti kaudu. Aga kuna pahategusid sooritavad muuhulgas ka jõnglased, kellel pole(veel) aimu HTTP protokolli töötamisest, ei tasu $_****'i unustada. Liiati kui see muudab koodi selgemaks ja paremini hallatavaks. (Varjasemates versioonides, enne PHP 4.1 olid $_* muutujate asemel kasutusel $HTTP_*_VARS muutujad, näiteks $HTTP_POST_VARS) Mõttetu muutujate kasutamine. Kui vaadata suvalise PHP programmi, olgu see siis vabavara või mitte, konfiguratsioonifaili, siis vähemalt 90% tõenäosusega avastad sa sealt suure hulga muutujaid. Muutujaid, mida mitte keegi eales skripti sees ei muuda. Nagu ntx: mysql andmed; vajalikud kataloogid failide lisamiseks; mingid limit'id jms andmed. Aga kui neid muuta ei ole vaja, miks nad siis muutujad on?? Ilmselt seetõttu, et isegi paljud kogenud programmeerijad pole harjunud kasutama konstante. Või isegi ei teata nende olemasolust! Lihne näide neile, kes esimest korda kuulevad. Konstandi defineerimine ja kasutamine: PHP kood:
...kasutades muutujate asemel konstante, ei anna me kellegile võimalust neid pahatahtlikel eesmärkidel üle kirjutada ning jällegi üks sammuke turvalisuse suurendamise suunas tehtud. eval() funktsioon ei ole sinu sõber... ...kui sa teda hoole ja armastusega ei kasuta. Kuigi kindlasti on olemas olukordi, kus on vaja eval'it kasutada, siis 90% juhtudest, mil teda kasutatakse, on täiesti mõttetud ning sama probleemi saaks ka muudmoodi lahendada. Eriti ohtlik on olukord, kus eval'it kasutatakse koos kasutajalt saadud andmetega. Üks levinuim olukord evali kasutamiseks on ühe muutuja nimetamine teise muutuja väärtuse järgi(ehk muutuja muutuja). Nt on meil muutuja: ..ja tahame tekitada muutuja $i väärtuse järgi muutuja 'kala', aga me ei saa seda niisama teha, kuna $i väärtus muutub iga kord. Selle asemel, et kasutada eval'it, tuleb lihtsalt kasutada kõige lihtsamaid muutuja muutujaid: PHP kood:
Selle tulemusena saame skripti(juhul, kui $i==kala) muutuja $kala='v22rtus'; Evalit kasutades tuleb seal sees kasutatavad muutujad alati hoolikalt üle kontrollida! Lisaks eval'ile on veel üks programmidegrupp, mille kasutamisse peab suhtuma väga suure ettevaatusega. Need on serveris programmide käivitamiseks mõeldud funktsioonid. Logimissüsteemid ja salasõnaga kaitstud lehed Olles eelnevad vead koodist kõrvaldanud, tuleks natukene mõelda ka programmi disainist tulenevatele vigadele, mis ei ole seotud mingi konkreetse koodireaga. Ja kõige tavalisem selline viga ongi kasutajatuvastamissüsteemi vale ülesehitus või valed vahendid selle ehitamiseks. Cookie kui andmete hoidja. Kui te kasutate küpsiseid kasutajatesüsteemi ehitamiseks, siis 1) lisage lehele märkus, et seda mõtet ei ole te saanud minu käest :) 2) arvestage, et see on kõige ebaturvalisem viis Miks? 1) Cookie ise on kriitiliste andmete hoidmiseks ebaturvaline 2) Pahatihti ehitatakse selline süsteem valesti ülesse: -kontrollitakse kasutaja sisestatud andmeid ning selle asemel, et igal lehe laadimisel passwordi ja salasõna kontrollida, salvestatakse kasutaja arvutisse cookie nimega 'logged' ja väärtusega '1' või 'logged' vms ning hiljem kontrollitakse ainult selle olemasolu. Samas kuna cookie on kasutaja poolt sinule antud info, siis võib kasutaja, oskuste olemasolul, seda lihtsalt võltsida ja pääseb vaevata sinu kaitstud keskkonda. Aga cookie'dest märksa mõttekam on kasutada sessioone. 1) Nad on turvalisemad 2) Mina soovitan neid cookiede asemel :) Turvalisemad on nad seetõttu, et sessiooni andmeid säilitatakse serveris, kasutaja käes on kõigest sessiooni nimi, mille alusel talle andmeid jagatakse. Kuigi oskusliku programmeerimise korral võib teha ka süsteemi, kus säilitatakse muutujat logged=1, siis mina ise kasutan igakordset kasutajanime ja passwordi võrdlemist andmebaasis oleva info vastu. Miks? PHP-koodi asukoht serveris Esiteks tuleks veenduda, et keegi teine sinu koodile ligi ei pääseks. Koodi nägemine kergendab sellest läbimurdmist tunduvalt, sest siis on teada, mis ees ootab. Selleks on vajalik, et keegi sinu koodi niisama ei näeks: nt hoida skripte kõigile nähtavas kataloogis parsimisele mittekuuluvate failinimedega. Tavaliselt parsitakse ära .php ja .php3 laiendiga failid, aga kuna see sõltub konkreetsest serverist ja selle administraatorist, siis on seda nimekirja võimalik järgmise jaanipäevani jätkata. Üldjuhul laialt kasutatavat laiendit .inc serverid ei parsi. Aga veelgi kavalam, kui eraldi koodijuppide äraparsimine, oleks nad paigutada kuskile veebist kättesaadavast kataloogist kõrgemale. Nt kui veebikataloog on /www/apache/user/htdocs/, siis oleks tore lisatavad php failid paigutada nt kataloogi /www/apache/user/phpfailid/. Sest PHP oskab asju skripti lisada ka väljaspoolt veebikataloogi. Külastajad aga neid faile käppida ei saa.. Teine asi on see, et isegi kui kogu programm on ehk turvaline, siis üksik fail võib ikkagi haavatav olla, mistõttu tuleks neid eriti hoolsasti kaitsta. Minu nimi on John Smith Ehk pahatihti on probleemiks mitte programmeerija, vaid isik monitori ja tooli vahel. Isik, kes sisestab oma passwordiks oma kasutajanime - imelihtne ju meelde jätta! Või kasutab salasõnana ülikeerulist tähekombinatsiooni, mida keegi kindlasti ära ei arva, nt 'password'. Samuti on mõnelpool tavaks esimene password kasutajale emailiga saata, mitte ei lasta tal seda ise valida. Milles probleem, küsid? Ei milleski, aga seda niikaua, kuni see esimene salasõna ei ole 'muudaara' või 'changeitnow' või mõni muu stamp, mis on kõigil uutel kasutajatel üks ja seesama. Sest hämmastavalt paljud kasutajad arvavad, et nood on head meelde jätta küll ning jätavad oma "salasõna" muutmata. Sellisel password-ekirjaga juhul tuleks igale kasutajale genereerida unikaalne ja kordumatu sõnaühend. Jõudsid siiamaani? Rõõm kuulda, ehk oli sellest lugemisest natuke kasu ka. Esiteks, kui sul on midagi lisada, siis tee seda kindlasti. Teiseks, see siin ei ole kaugeltki kõikehõlmav artikkel. Kindlasti on veel palju probleeme, mis siin käsitlemata jäid. Kolmandaks, siin artiklis ei ole käsitletud serveri konfigureerimisest tulenevaid probleeme (kui lugejate hulgas on keegi, kes seda teha sooviks, siis see oleks ülitore). Tihtipeale võib pahalane sisse tulla ka serveri adminni "näpuka" tõttu. Ja lõpuks, turvalisus ei ole veebitarkvara ehitamisel mitte kolmandajärguline asi ja hetkel on ta selgelt alatähtsustatud või õigemini alateadvustatud. Suurim probleem turvalisuse juures ongi see, et asju tuleb terviklikult vaadata: iga rida eraldi võib olla ok, aga kui programmi tehniline disain on halb, siis võib ka sealt turvaauk "sisse tulla".. ..ja vastupidi: on kenasti läbimõeldud programm, aga ühe pisikese näpuvea tõttu muutub haavatavaks. Korraliku programmi iva võiks olla see, et turvalisus ei ole kunagi selline asi, et nüüd võtan kätte ja progen oma superlahedale programmile turvalisuse ka juurde - selline suhtumine tavaliselt viibki probleemideni. Turvakontroll peab programmi läbima igal tasemel - lihtsaimast MySql käsust tööpõhimõteteni. Vaevalt, et ükski programm kunagi 100% turvaline on, aga haavatavuse tõenäosus võib hea programmi korral küll nullilähedale langeda. Tarkvara on tarkvara alles siis, kui ta suudab ellu jääda ka lollide kasutajate ja dumbade süsteemiadministraatorite kiuste. Artikli kommentaarid |
|