razprave B Preverjanje vhodnih podatkov v spletnih rešitvah s Perl in PHP Ivan Verd on ik i van verdonik@sml net, ivamHrdDnik@hot.mail.com Povzetek Zlu rabe v spletnih rešitvah so vedno pogostejše, saj klasični požarni zid navadna dobro varuje lokalno omrežja podjetja pred napadalci in se ti zato usmerijo na nove oil|e Požarni zidovi za spletne aplikacije še niso toliko v uporabi, pa tudi povsem zanesl|ivi niso Zaradi tega moramo pri programiranju spletnih rešitev uporabljati varnostne mehanizme, ki jih ponujajo orodja za izdelavo aplikacij sama. V prispevku smo se usmerili na obdelavo varnosti spletnih rešitev v programskih jezikih Perl in PHP, ki se pogosto uporabljata v ta namen. Poleg tega bomo pokazali nekatere splošne spletne ranljivosti, ki so značilne za vsa orodja. Z varnostnega vidika je najpomembnejša obravnava vhodnih podatkov [8], Abstract Input data validation in web applications with Perl and PHP Attacks on web applications are increasing rapidly, because company intranet is sufficiently protected by classic firewalls therefore hackers fncus nn new areas. Web application firewalls are available, but they are not widely usad and they are not always reliable Therefore, security mechanisms, which are already provided In programming languages should be applied when programming web application. We must also follow security guidelines. The paper focuses mostly on security issues and protection of Perl and PHP programming languages, but to a certain extent also on some other common web vulnerabilities From web application security viewpoint, the input data validation is the most critical [8] issue. 1 Uuod Spletne aplikacije temeljijo na znani arhitekturi MUC (Model Uiew Controller): uporabniški odjemalec je spletni brskalnik, umesni člen je aplikacijski strežnik, v katerem se nahaja programska logika, tretji člen pa je podatkovna zbirka. Spletne rešitue so use bolj razširjene in podjetja jim posvečajo uedno več pozornosti, tako tista, ki ponujajo orodja za njihovo izdelavo, kot druya, ki spletne rešitue programirajo in tretja, ki jih uporabljajo. Zaradi takšne razširjenosti, pa tudi zato, ker njihoua varnost še ni povsem dorečena, so spletne rešitue priljubljena tarča hekerjeu. Ne glede na uporabljeno tehnologijo (operacijski sistem, spletni strežnik, aplikacijski strežnik, programski jezik, SUPB sistem za upravljanje podatkovnih baz) obstaja več tipov spletnih napadov, ki ogrožajo vse: skripte med spletnimi mesti (XSS - Cross-Site Scripting), SQL vrivanje (SQL injection), premikanje med imeniki (path traversal), URL kodiranje, spreminjanje HTML form (Form Tampering), kanonikal-izacija (Caupnicalization), kiiii funkcij operacijskega sistema ipd. 11 j PrakdČno vse te ranljivosti spletnih rešitev izvirajo iz ne dovolj preverjenih uporabniških vnosov. Preverjanje ni preprosto, k sreči pa je v večini program- skih jezikov, ki se uporabljajo za programiranje spletnih rešitev, na razpolago več uporabniških funkcij, s katerimi brez prevelikega napora zmanjšamo možnosti zlorab |5|. Spletno rešitev lahko v celoti izdelamo z brezplačnimi orodji (in takšnih je največ), zato smo se odloČili za predstavitev varnostnih groženj in zaščite pred njimi, v zelo razširjenemu Perlu ter posebej PHP-ju. Sicer obstaja še kar nekaj drugih skriptnih jezikov za ta namen (npr. Tcl/Tk, Python, Ruby idr.), ki pa zaenkrat še niso tako uveljavljeni. 2 Kratek uvod u regularne izraze Regularni izrazi so jezik končnih avtomatov, kot so definirani v teoriji računalništva. V pričujočem članku jih veliko uporabljamo. Njihova sintaksa je v obeli jezikih, ki ju obravnavamo (Perl in PHP) enaka. 7, njimi opisujemo znakovne nize in nad nizi izvajamo operacije iskanja in zamenjave. Sestavljeni so iz vzorcev običajnih znakov in m etažna kov. Vzorec je lahko sestavljen iz enega ali več znakov. En alfanumerični znak predstavlja samega sebe, znak pike (.) predstavlja poljuben znak (z izjemo znaka za novo vrstico). 1h upuhiiini informatika 2004 -ilevilka 1 !olr,ikXIV Ivan Ver d on ¡k: Preverjanje vhodnih podatkov v splelnih rešitvah s Perl in PHP Znaka za oglati oklepaj vsebujeta seznani znakov (npr. /| 1234|/ pomeni, da mora v nizu biti znak 1, ali 2, ali 3, ali 4). Če je vzorec sestavljen iz več znakov, uporabljamo tudi »sidrenje« (anchoring) vzorcev, mogoče pa je tudi iskati po metaznakih samih s pomočjo leve poševnice (npr. A.\|\|/ niz mora vsebovati podniz | ). Z uporabo pomišljaja lahko prikažemo razpone (npr. /[(M>|/ niz mora vsebovati eno od cifer, /| A-Za-z0-9_]/ vsebuje enega od alfianumeričnih makov .,.). Poleg tega imamo bližnjice za najpomembnejše skupine znakov in njim inverzne množice znakov (npr. \d cifre, \D ne-cifre. \w besede, \W ne-besede, \s tabulator)!, znaki za novo vrstico, presledki in \S nasprotje tega). Vzorci običajno vsebujejo več znakov, ne le enega, Povežemo jih z združevanjem v zaporedje, alternativnimi možnostmi, navajanjem števila ponovitev enega ali več znakov. Nadalje lahko z okroglimi zaklepaji določimo prednost ali pa jih uporabimo za pomnjenje. Zaporedje znakov podamo preprosto tako, da navedemo več znakov (ali njihovih skupin) neposredno enega za drugim (npr./113/ ta niz mora vsebovati število 113, /Windows 5\.0/ ta pa Windows 5.0 ...). Alternativno izbiranje med možnostmi podamo z znakom | (npr. niz mora vsebovati enega od osebnih /.a i m ko v ^az|tijpn|ona|ono|mi|ine|vi|ve|oni|one/). Za podajanje števila ponavljanj znaka ali več znakov uporabljamo naslednje oznake: ? nič ali en znak * tlič ali več -H eden ali več (m,n| od m do n ponavljanj (m,| iti ali več ponavljanj {.,n} največ ti ponovitev (i ( točno i ponovitev Npr. /ha + ha/ niz vsebuje nekaj od haha, haaha, haaaha ..., /ha (31 ha/ niz vsebuje haaaha. Okrogli oklepaji se lahko uporabljajo kot pomnilnik kje naprej v vzorcu (npr. /(spredaj) (zadaj) obratno V2\ i/vsebuje niz: spredaj zadaj obratno zadaj spredaj). S sidrenjem vzorcev je mogoče opredeliti mesto vzorca znotraj niza (npr: /AIvan Caf/ pomeni, da mora na začetku niza biti podniz Ivan Caf,/dipl\.ing\.$/ pa da je tik pred koncem niz dipl. ing.). V regularnih izrazih obstaja operator ujemanja (match operator), ki vrne vrednosti resnično ali neresnično glede na to, ali je regularni izraz vsebovan v nizu ali ne. Označen je kar z/regularni izraz/, pa tudi z m/regularni izraz/ ali m#regularni izraz# ali m{regularni izraz}. Nadalje obstaja operator = -, ki veže rezultat operatorja ujemanja na podano spremenljivko (npr. if ($odlocitev = - /|Dd \f) then .,.), temu nasproten operatorje ! - (npr. if ($odlocitev !~/jNn[/} then ...). Naslednji je operator zamenjave (substitucije) podanega vzorca z regularnim izrazom. Sintaksa je: s/ vzorec/na do m es tni_niz/ (npr. s/W i n d o w s/I, i n u x/ zamenja podniz Windows z nizom Linux, $ jezi k = - s/C/ Perl/ v spremenljivki Sjezik zamenja znak C z nizom Perl, v tem načinu izvede samo eno zamenjavo). Če hočemo, da zamenja vse pojavitve vzorca, moramo na koncu dodati smernico g (npr. Sjezik - - s/C/Perl/g). Povedali smo že, da spremenljivke VI, \2, ... hranijo pod nize, ki se nahajajo v regularnem izrazu znotraj okroglih oklepajev. Vendar jih na ta način lahko uporabljamo samo v njegovem okviru. Ce hočemo te pod-nize uporabljati naprej v kodi, jih lahko beremo v spremenljivkah $1, $2, ... (npr. $ime = ~ m/Od:(.*)/; $ pošilja tel j = $1; ...). Več informacij o regularnih izrazih najdete v 11()|. 3 Perl in Pert CGI I'erl (Practical Extraction and Report Language) je splošni namenski programski jezik, ki se izvaja v okviru navideznega stroja. Zaradi tega deluje na vseli platformah, za katere obstaja tak stroj. Ti obstajajo za tako rekoč vse bolj znane operacijske sisteme, predvsem za različice Unixa in Linuxa, pa tudi za Windows. I'erl je enostaven za uporabo in omogoča tako proceduralno programiranje kol tudi objektno usmerjeno, zanj pa obstaja tudi velika (brezplačna) zbirka modulov 1111. Perl je izpeljan in izdelan iz programskega jezika C (vendar nima kazalcev) in vsebuje zmožnosti nekaterih orodij iz lupine operacijskih sistemov Unix {npr. sed in awk). Perl in ničelni znak Prva varnostna pomanjkljivost v Perlu je nedorečena obravnava ničelnega znaka (to je znak DO oziroma %00). Kot vemo, ta znak v programskem jeziku C predstavlja konec niza. V Perlu bi ta znak (ne smemo ga zamenjati z znakom 0 ali presledkom) moral hiti takšen kot vsak drug znak, kar pa ni vedno res, saj je Perlov interpreter programiran s C. Tako je mogoče z znakom \U kraj i a ti nize (in prek njih ukaze), obenem pa niz *niz\0' ni enak nizu 'niz'. Iz tega izvira kar nekaj varnostnih problemov [6|. 200A - Številka 1 -letnik XIV uporabna INFORMATIKA 25 Ivan Ver d on ¡k: Preverjanje vhodnih podatkov v splelnih rešitvah s Perl in PHP Primer krajšanja nizov: V svetovnem spletu je več aplikacij, ki kot parameter sprejmejo spletno stran, pri čemer privzamejo, da je njihova končnica htm] (in jo dodajo sami). Poenostavljeni primer taksnega programa, ki prikaže podano Spletno stran v brskalniku, je: testlzpisCgi.pl #!/usr/bin/perl use CGI; $ poizvedba = new CGI; print $poizvedba->header; Sstran - Spoizvedba->pa/am(splatnaStran'); open (FILE, "<$stran.h1mO; while () {print "$_";} close (FILE); Zgornji program deluje V redu, če za parameter spIetnaStran podamo dejansko html datoteko npr. test.htm i: http ;//iocalhost/. 7scriptstestlzpisCgi.pl? spIetnaStran=/ i n et p u b/wwwroot /1 es( V tem primeru je rezultat takšen, kot ga je razvijalec načrtoval. Toda če podamo npr.: httpV/localhost/.Vscripts/testlzpisCgi.pl? spIetnaStran=testlzpisCgi. pi%OÜ skript prikaže svojo lastno kodo (to je v tem primeru program, ki izpiše samega sebe), če mu podamo kateri drugi skript, pa seveda izpiše tudi njegovo kodo. Znak %lJ(t je URI., kodirana oblika znaka \0. Problem je v tem, da Perl pri tem, ko odpira z nizom podano datoteko, upošteva le del niza pred tem znakom. Na ta način bi si napadalec na operacijskih sistemih Unix/ Linux lahko izpisal datoteko /etc/passwd. Gesla v tej datoteki .so šifrirana, vendar imajo pogosto premajhno entropijo. Zato jih lahko, če jo napadalec pridobi v posest, odkrije s programom za ugibanje gesel. Takšna pr ograma sla na primer LC5 in John the Ripper. Ta problem v Perlu obstaja povsod, kjer v kodi vhodnim podatkom dodajamo pripone. Težave povzroča tudi dejstvo, da je niz 'nizAO' včasih enakovreden nizu 'niz', včasih pa ne. Posebej pri primerjanju v pogojnih stavkih, sta ta dva niza različna. Težav z ničelnimi znaki se v Perlu enostavno ognemo tako, da iz vhodnih podatkov odstranimo vse ničelne znake, to je mogoče storiti z naslednjo substitucijo: $vhodni_podatek s/\0//g: Težave s poševnicami Pogost varnostni problem so tudi poševnice. Po priporočilih konzorcija W3C so znaki s posebnim pomenom za Linux/Unix lupino operacijskega sistema: & ; • ■ \ ■■ | ■ ? ~ <>«<)[]{}$ V Kadar se v vhodu v program pojavijo ti znaki, jih moramo predstaviti z ubežnico (escape), sicer ohranijo svoj posebni pomen (Npr. > preusmeritev, \n nova vrstica ...). V ta namen nad vhodnimi podatki uporabimo naslednjo substitucijo: SvhodnLpodatck = ~ s/( [\V \\\ j "*? ~ <>A\(\)\[\]\{\)\$ \ n\r])/\\$1 /g; Tako postanejo običajni znaki brez posebnega pomena. Če programerji na to pozabijo, je posledica v najboljšem primeru nepravilno delovanje, v slabem pa varnostne pomanjkljivosti, kot so razkritje vsebine občutljivih datotek, SQi. vri vanje itd. Predvsem se pogosto zgodi, da ti znaki sicer so predstavljeni / ubežnico, vendar ne tudi znak leve poševnice (\ - backslash) [6], Če ne uporabimo ubežnice za leve poševnice, zlonamernemu uporabniku ne moremo preprečiti dostopa do imenikov in datotek z naslednjo substitucijo: Swhodni_podatek s/\.\.//g; Naš namen je, da i/ vhodnega podatka odstranimo znak za premik navzgor po strukturi datotečnega sistema (..). Če npr. napadalec za ime datoteke poda: /usr/tmp/../../etc/passwci to postane: / u sr/tmp///etc/p33swd 26 upohauh* informatika 20M - Številko I ■ Mmh XIV Ivan Ver d on ¡k: Preverjanje vhodnih podatkov v splelnih rešitvah s Perl in PHP s čemer napadalec ne doseže želenega rezultata, ker je dovoljeno podati več zaporednih poŠevnic in se tako ne more dvigniti i/ trenutnega imenika navzgor. Toda če leva poševnica ni podana z ubežnico, je zgornji varnostni ukrep mogoče zaobiti z naslednjim vnosom: /usr/tmp/ ,\./.\. /etc/ passwd Regularni izraz ne deluje zaradi leve poševnice, zato napadalcu njegov namen uspe. Rešitev je tudi tu preprosta, paziti moramo, da tudi za levo poševnico uporabimo u bežni znak (torej tako Težaue s ceumi V Perlu imamo pri odpiranju datotek s stavkom open() možnost, da podamo ukazno vrstico kot vhod oziroma izhod. To je mogoče, če pred (izhod) ali za njo (vhod), dodamo znak j. Sintaksa je naslednja: open (DATOTEKA, "|ukazna vrstica1}; - odpre datoteko za pisanje Open (DATOTEKA, "ukazna vrstica|"): - odpre datoteko za branje Primer programa za neposredno tiskanje na tiskalniku: open (TISKALNIK, "|lpr"), print TISKALNIK Spodatki; Close TISKALNIK; Primer izpisa vsebine trenutnega imenika: Sizpis - "dirj"; open (DATKA. Sizpis); while () { print $_r\n"; } dose DATKA; Napadalec pridobi dostop do ukazne vrstice, če poda spremenljivki $datoteka spodnjo vrednost [8]: Sdatoteka j "c;\\wlnnt\\system32\\cmd.exe|"; openfDATKA, Sdatoteka): while () { print $..,"\n"; ) close DATKA; Zlorabam s pomočjo cevi se je mogoče preprosto izogniti, če pri odpiranju datotek s funkcijo open(), podamo /nnk '<' (branje),'>' (pisanje) ali '>>' (dodajanje). Primer je: Sdatoteka = "c:\\wlnnt\\system32\\cmd.exe |"; openIDATKA, "<.$datoteka"); Mogoče je tudi filtrirati znak za cev | z: Svhod =~ s/(\|tA\$i/g Ueljaunost znakov u zapisu UTF-8 UTF-8 kodiranje omogoča prikaz tako rekoč vseh obstoječih znakov, predvsem znakov i/ abeced naravnih jezikov. Vrsto kodiranja v dokumentih XML, XHTML in HTML določimo: 1. z uporabo parametra 'charset' v glavi HTTP: Content-Type: text/html; charset »UTF-8 2. za XML (in XHTML) z psevdo atributom 'encoding': 3. v HTML uporabimo oznako v : Kadar naša aplikacija s formami sprejema UTF-8 kodirane znake, jih preverimo z naslednjim testom: $veljaven_vnos =~ m/A({\x09 \xOA\xOD\x20-\x 7E] # ASCII I [\xC2-\xDF]{\x80-\xBF] # 2 bajtna ne-predolga oblika I \xEO[\xAO-\xBF][\x80-\xBF] # Vključimo predolge oblike I l\xE1-\xEC\xEE\xEF][\x80AxBFl{2] # neposredne 3 bajtne oblike | \xED[\x80-\x9F][\x80-\xBF] # Izločimo nadomestke I \xF0 [ Vx 9 0- \xB F] [ \x8 0 - \xB F] (2) # nivoji 1-3 I [\xF1 -\xF3][\x80-\xBF]{3) # nivoji 4-15 I \xF4[\x80-\x8F|[\x80-\xBF]{2) # nivo 16 )'$/x; 2UÜ6 šlevil ka l - Jelmk XIV u e o n * o h t INFORMATIKA 27 Ivan Ver d on ¡k: Preverjanje vhodnih podatkov v splelnih rešitvah s Perl in PHP Če je vnos regularen, je rezultat 'true', drugače pa 'false'. Če tega ne naredimo, lahko napadalci tvorijo nelegalna UTF-8 kodiranja na dva načina: • UTF-8 zaporedje za posamezen znak je lahko daljše, kot je potrebno; • UTF-8 zaporedje lahko vsebuje neveljavne bajte, ki niso v skladu z nobenim od formatov. Spletni strežniki in spletne aplikacije praviloma izvajajo več stopenj obdelave vhodnih podatkov, od njihovega zaporedja pa je lahko odvisna varnost. Zaporedje je sestavljeno iz dekodiranja URI,, ki mu sledi dekodiranje UTF-8, vse skupaj pa je premešano še z raznimi varnostnimi preizkusi. Primer nevarnosti je, če npr, aplikacija testira, ali vhod vsebuje dve piki {,. - direktorij navzgor) pred dekodiranjem UTF-8, je mogoče dve piki vstaviti s "predolgim" formatom UTF-8. Tudi Če je to preverjeno, imamo npr. za predstavitev znaka pike (AE) Se pet drugih (predolgih) predstavitev (CO AE, Ft) 80 AL, FO 80 80 A F, F0 80 80 80 AE hi FC 80 80 80 80 AH). Če nadalje pogledamo predstavitev CO AL, morata biti najpomembnejša bita drugega bajta 10, ker tega nekatere aplikacije ne preverjajo, je mogoče tudi "00", "01" in "11" in so tako dodatne možnosti predstavitve še CO 2F, CO 5E in CO FE. Stvari so Še bolj zapletene glede na dejstvo, da je mogoče podatke poslati s protokolom HTTP v vee oblikah, npr. v surovi, to je brez vsakega kodiranja URI , kar pomeni pošiljanje ne-znakov ASCII, v poti, povpraševanju in telesu, kar sicer ni v skladu s standardom HTTP, vendar jih večina 111TP strežnikov vseeno sprejme. Veljavno kodiranje URL zahteva, da je vsak ne-ASCIl znak URL kodiran (to bi pomenilo, da moramo zgornji CO AF kodirati kot %C0%AF). Pri neveljavnem kodiranju URL so nekatera heksadeci-malna števila zamenjana z neheksadecimalnimi števili, rezultat pa se ponekod interpretira tako kot izvorni {npr. %G0 se interpretira kot število znaka - ('C-'A'+ 10)* !6 + ('0'-'0') = Idir+c:\ lahko poskusi še z naslednjim URL kodiranjem napada: http : //strežnik/cgi-bin / napaden. pl?vnos . .%2F . /winnt/ system32/cmd,exe?+/c+dir+c:\ ter še s štirinajstimi različnimi Unicode kodiranji napada [2 j. Preprečevanje napadov s skripti med spletnimi mesti Skripti med spletnimi mesti (Croos-Siie Scripting -XSS) so pogoste varnostne težave pri spletnih rešitvah (ki jih razvijalci zaradi časovnih rokov in zahtevnosti pogosto prezrejo) [3]. Spletišče je ranljivo, če spletna rešitev prikaže vsebino, ki jo je vnesel uporabnik, in ne preveri, ali so v vsebini zlonamerne skriptne oznake. Tako navadno zlonamerni uporabniki napadajo druge uporabnike prek spletnih mest tretjih oseb. Primer ranljivega programa: #!/usr/bin/perl use CGI, my Scgi = CG!->new(); my $ vri os - $cgi->param('vnosno_polje'); print $cgi-> header!); print "Vnesli ste $vnos"; Napadalec lahko v parameter 'vnosnopolje* vpiše zlonamerno (Javascript, pa tudi 11TML) kodo. Na primer: Hvala za va( piškotek Ce napadalec navede neprevidnega uporabnika, da izbere takšno povezavo, mu bo njegov brskalnik prikazal trenutno množico piškotkov. Napadalec lah- 28 uporaetha informatika 2006 - Številka 1 - letnik XIV Ivan Ver d on ¡k: Preverjanje vhodnih podatkov v splelnih rešitvah s Perl in PHP ko poda tudi mnogo nevarnejšo kodo - kodo za krajo gesel, preusmeritve na zlonamerna spletna mesta (npr. trojanske spletne banke)... Pri spletnih rešitvah, ki temeljijo na Peri CGI in mod_perI, zmanjšamo nevarnost skript med spletnimi mesti tako, da opravimo ustrezno preverjanje vhodnih podatkov, kot npr.: $preverjen_vnos s/[AA-Za-zO-9 ]*/ /g, Tako ohranimo samo velike in male črke, števila in presledke. To je zanesljiva zaščita, vendar je pri nekaterih aplikacijah to prehuda omejitev. V takih primerih {kadar so potrebni tudi znaki s posebnim pomenom) je odstranjevanje zlonamernih elementov iz vhodnih podatkov mnogo težje. Druga možnost je, da preden prikažemo vsebino, oznake HTML predstavimo z ubežnicami. Za ta namen obstaja peri modul HTML::Hntities s funkcijo HTM L;; En ti ties;: e ncode(), ki pretvori znake HTML v reference entitet HTML. Npr. znak'c1 pretvori v '<', '>' v '>',"" v *"' Zgornji program zavarujemo z zamenjavo oznak ¡HTML v reference entitet HTML, z omenjenim modulom, kot je podan spodaj: #!/usr/hin/perl use CGI; use MTML::Entities; my Scgi = CGI->new(); my $vnos " $cgi->param('vnosno_polje'); print $cgi-Hieader(). pri nt "Vnesli ste", HTML:.Emilies: :encode(£vnos); Če uporabljamo mod_perl {tj. Perl, povezan s spletnim strežnikom Apache, posebej namenjen za spletne aplikacije), je za programerje še bolje poskrbljeno, saj imajo poleg zgornjih rešitev tudi modul, posebej namenjen za preverjanje uporabniških vnosov. Imenuje se Apache::TaintRequest. Primer njegove uporabe: use Apache: :TaintRequest (): sub handler ( my $r - shift; $r - Apache: :TaintRequest->new($r); my $niz » $r->query_string(}; 5r->print($niz); # html oznake so prikazane z ubc'nicami ) Dobra preventiva pred temi napadi je tudi, če v brskalniku izključimo skriptne jezike (Javascript, JScripi, VBScript,..). Preprečevanje SOI uriuanja Kadar spletna aplikacija dostopa do podatkovne zbirke na osnovi uporabnikovega vnosa, lahko napadalec z ustrezno prirejenim vnosom zlorabi podatkovno zbirko. Takšne napade imenujemo SQL vri-vanje Injection) [3]. Ranljivost ponovno izvira iz ne dovolj preverjenih vhodnih podatkov. Ker je težko odkriti vse nevarne konstrukte, je bolje odstraniti vse, razen dovoljenih, kar pa je včasih v praksi težko storiti. Primer je lahko naslov elektronske pošte. Dovolimo samo male in velike črke, cifre, afno, piko, pomišljaj in podčrtaj. Toda ker imajo nekateri dokaj nenavadne naslove (ki vključujejo npr. znake + itd.), so pri takšnem preverjanju izločeni, kar lahko za lastnika spletišča pomeni ekonomsko škodo. Oglejmo si primer za SQL vrivanje ranljive kode. #!/usr/bin/perl use CGI; my Scgi - CGI->new(), rny Sime = $cgi->param(vnosno_polje 1): my Sgeslo - $cgi->param( Vnosno polje2'): my Sstti = $dbh->prepare ("SELECT ■ FROM uporabniki WHERE uporabnik $ime and up_geslo = Sgeslo "}; $sth->execute(); Če napadalec za $ime poda npr. »' 'or 1=1« in isto za $ges!o, bo program odvisno od nadaljnje kode izpisal prvo vrstico iz tabele uporabniki ali celo vse vrstice. V tem primeru je dejanski SQL stavek, ki se izvede: SELECT * FROM uporabniki VVHERE uporabnik = " or 1 = 1 and up_geslo = '' or 1 - 1 Na podlagi tega principa je mogočih veliko zlorab. 7. znakom - - je mogoče krajšati stavke SQI. (ta znak namreč pri večini podatkovnih zbirk predstavlja znak 2D0i - številka 1 ■ letnik XIV »nuni INFORMATIKA 29 Ivan Ver d on ¡k: Preverjanje vhodnih podatkov v splelnih rešitvah s Perl in PHP za komentar), Z znakom ; pa je mogoče dodajati dodatne SQL stavki1. Zaščito močno okrepimo, če za spremenljivke uporabimo nameščanje (placeholder). Zgornji primer bi spremenili v: #new(), my $ime = Scgi->param(Vnosno_polje 1'); my Sgeslo » $cgi->param(,vnosno_pol]e2'); my Ssth ■ $dbh->prepare ("SELECT ' FROM uporabniki WHERE uporabnik = 7 and up_geslo = ? "); $sth->execute($ime, $geslo); Če napadalec npr, za $ime in Sgeslo ponovno poda ' or 1 = 1«, je stavek SQL, ki se dejansko izvede: SELECT * FROM uporabniki WHERE uporabnik = '" or 1-1' and up_geslo - "' or 1-1" in tako ne doseže svojega namena. Za nadaljnje izboljšanje zaščite pred vri van j eni SQL je kot pri prejšnjih sekcijah treba vse znake s posebnim pomenom predstaviti / ubežnico. V podatkovni zbirki MySQL za ta namen obstaja funkcija: mysq[_real_escape_string() v Perlu pa metoda DBD; $d bh->quote($slavek). K boljši varnosti pripomore tudi, če je aplikacija zasnovana tako, da so opozorila vidna samo skrbniku, ne pa tudi uporabnikom. Zlonamerni uporabnik tako ne more spoznati strukture podatkovne zbirke. Če ni tako, lahko napadalec s posebej sestavljenimi (napačnimi) vnosi sondira zbirko. 4 PHP Globalne spremenljivke V različicah PHP pred 4.2.0 je v inictalizacijski datoteki php.ini direktiva register^globals po tovarniških nastavitvah nastavljena na ON. V tem primeru PHP ne preverja, kje je bila določena spremenljivka iniciali-zirana [7], Zaradi tega lahko (zlonamerni) uporabnik sam nastavi njeno vrednost v URI. vrstici ali vnosnem polju. Za ilustracijo poglejmo skript: # slabo, php Problem s tem skriptom je, da je mogoče spremenljivko Sdovoljeno nastaviti na "D" v vrstici URL: http://www. slab. sislabo.php?uporabnik-peter& geslo -skrivno&dovoljcno-D V takem primeru bi se $obcutljiv_podatek izpisal ne glede na to, ali je uporabnik pooblaščen ali ne. Težavo rešimo tudi, če vse spremenljivke V skripta iniciaiiziramo, preden jih uporabimo. Npr.: U dobro.php Aplikacijo je mogoče razvijati tudi z direktivo errof_reporting E_Al.l , vendar je najlaže izključiti register globals (oziroma ga pustiti izključenega) |7j. Vključevanje datotek i medmreija Kadar skripte vsebujejo kodo, kot je: \n"); 7> in napadalec uspe nastaviti spremenljivko $datka na vrednost /etc/passvvd, bo ta program mogoče izpisal datoteko z gesli. Mogoči pa so tudi manj pričakovani napadi, ki izvirajo iz vključevanja datotek/, oddaljenih lokacij |7|. Poglejmo skript: 3D u p o * » a k a informatika 2006 - številka 1 talnih XIV Ivan Ver d on ¡k: Preverjanje vhodnih podatkov v splelnih rešitvah s Perl in PHP in ga prav tako poimenuje knjižnica!,php. Tako se bo izvedel napadalcev skript in prav tako izpisal datoteko z gesli. Napadalec mora paziti le, da na njegovem spletišču ni mogoče izvajati datotek tipa php, sicer se skript izvede na njegovem spletnem mestu. Nalaganje upora bnikouih datotek PI IP omogoča uporabnikom, da nalagajo svoje datoteke na spletna mesta. Pri tem uporabljamo HTML FORM element {z ustreznimi INPUT elementi). Primer takšne kode HTML:
. S PHP 4.0 in naprej je za seje se bolje poskrbljeno. Večina podatkov o uporabnikovem stanju (oziroma seji) je shranjena na spletnem strežniku, na uporabnikovi strani je le preprost piškotek {v njem je samo oznaki seje PHPSE5S1D). Obstaja pa tudi možnost, da oznako seje prenašamo z URL-ji. Glede na to, da je PHPSESSID ključ do uporabnikove seje, ne sme priti v roke drugim uporabnikom (napadalcem). Ti sega včasih vseeno polastijo tn sicer z ugibanjem, zajetjem piškotka ali fiksiranjem [7], S pomočjo tega ključa lahko napadalec ugrabi sejo legalnega uporabnika in jo zlorabi. Napada s pomočjo lik-siranja se ubranimo tako, da generiramo novo oznako, kadar uporabnik poda oznako seje, ki ni aktivna |4|. To lahko storimo z naslednjo kodo: Klici zunanjih funkcij Kadar v svoji spletni rešitvi uporabnikom omogočimo uporabo naslednjih zunanjih PHP funkcij: 1. string exec (string ukaz |, array &izhod |, in t &retu rn_var] ]), 2. string system (string command |, int ¿¿return _var]), 3. void passthru (string ukaz t, int &retum_var|), 4. operator levi črtici' 1 (backticks), 5. resource popen (string ukaz, string način), 6. funkcije requireO, include(), eval() ter preg_ re-place() z možnostjo 'e', moramo uporabniške vnose obdelati s funkcijama |7|: 1. string escapeshellcmd(string ukaz), 2. string efidapeshel la rg( string arg). Prva predstavi znake s posebnim pomenom za lupino operacijskega sistema z ubežnicami. Konkretno pred naslednje znake postavi levo poševnico: |*?~o*()[Ji }$\,\xOAj, VxFF. Znaka ' in", pa le kadar ne nastopata v parih. Na operacijskih sistemih Okna pa iste znake in še znak % spremeni v presledke. Druga funkcija postavi vhodni niz med enojne narekovaje, v primeru pa, da so v nizu že enojni narekovaji, doda še vsakemu od njih enojni narekovaj ali levo poševnico. Ti funkciji torej uporabljamo za varno predstavitev argumentov sistemskim ukazom. Pomembna zaščita, kadar imamo na istem strežniku več spletnih mest (pogosto pri spletnem gostovanju), so tudi ustrezne nastavitve načinov safemode, safe_mode_exec_dir, safe_mod e_gid, safe m o d e_i nclude_d i r, safe_mode_allowed_env_vars, safe_mode_protected_env_vars, open_basedir, disable_functions in disable_classes |4|. Prav tako kot pri spletnih aplikacijah s Perlom so tudi PHP aplikacije ranljive za napade XSS, SQL vri-vanje... Pred njimi se varujemo s filtriranjem vhodnih podatkov ter z uporabo funkcij |7]: 1. string htmlspecialchars (string niz [, int quote_styie I, string charsetl]), s to funkcijo preprečimo napadalcu, da bi kot vhod podal HTML vnos (pričakujemo navaden niz). Primer uporabe: Test 2. string striptags (string niz string allovvable_tags]), ta funkcija skuša iz niza odstraniti vse HTML in PHP oznake. Primer uporabe: Testni odstavek

<>— Komentar -> Drugi tekst'; echo strip tags{$tekst); //Izpiše: Testni odstavek Drugi tekst echo "\n"; // Dovolimo oznako

echo strip_tags($tekst.

); // lzpi{e

Testni odstavek Drugi tekst ?> 5 Sklep Peri in predvsem PHP sla zelo priljubljena skript na jezika za izdelavo spletnih aplikacij. Te so pogosto tarče hekerjev, ker v njih za varnost ni dovolj dobro poskrbljeno. Poleg splošnih nevarnosti (XSS, SQL Injection ...), ki grozijo vsem spletnim rešitvam ne glede na tehnologijo, smo si podrobneje ogledali specifične slabosti v omenjenima jezikoma in pokazali načine, kako jih ublažiti. Specifične slabosti v Perlu so ničelni znak, poševnice in težave s cevmi. 32 uro informatika 2006 - številka 1 - letnik XIV Ivan Ver d on ¡k: Preverjanje vhodnih podatkov v splelnih rešitvah s Perl in PHP Specifične težave PHP-ja so globalne spremenljivke, vključevanje datotek, nalaganje uporabniških datotek ter mehanizem sej med brskalnikom in strežnikom. Ranljive so tudi komercialne rešitve, kot so Microsoftov ASP.NET in IBM-ov Websphere; za vse pa velja, da mora za varnost poskrbeti predvsem razvijalec sam. 6 Uiri in literatura [1] Michael Howard, David LeSlanc: Writing Secure Code, Microsoft Press. 2003. [2J Ivan Verdonik, Tomaž Bratuša: He ker ski vdori in zaščita, Založba Pasadena, 2005. [3] Lincoln D. Stein, John N. Stewart: The World Wide Web Security FAQ, http://www.w3.org/Security/Fari/www-security-faq.html. 2005. [4] Ian Gilfillan: Secure Programming with PHR http:// www.webdeveioper.com/security/. 2005. [5] Jeremiah Grossman, Sverre H. Huseby, Amit Klein, Mitja KolSek, Aaron C. Newman, Steve Orrin in drugi: Web Application Security Consortium: Threat Classification, 2005. 16] Perl Security, http://www.xav.com/perl/lib/Pod/ perl see. html, 2005. [7] Dave Clark: PHP Security Mistakes, http:// www.devshed.corrVc/a/PHP/PHP-Security-Mistakes/, 2005. [8] Stuart McClure, Joel Scambray, George Kurtz:Hacking Exposed Filth Edition: Network Security Secrets & Solutions, McGraw-Hill/Osborne, 2005. [9] Grefi Hoglund, Gary McGraw: Exploiting Software: How to Break Code, Addison-Wesley, 2003. [10] Regularm izrazi: http;//wvw,regglar.-:^J?.t£aSKJD5,lDis/ tutorial.html. 2006. [11] R. Allen Wyke, Donald B. Thomas: Peri a Beginner's Guide. Osbome/McGraw-Hill, 2001. Ivan Verdonik je leta 1993 diplomiral na Fakulteti m računalništvo In informatiko Univerze v Ljubljani ter magistriral leta 2005 na Fakulteti ¿a elektrotehniku in računalništvo Univerza v Mariboru. Je avtor več členkov v p al j ud no s trakovni h revijah (Monitor, Varnostni forum) in glavni avtor knjige Hekerski vdori in zaščita Prispeval je dve predavanji na računalniških konferencah. Ukvarja se z raznimi vidiki računalniške varnusti in kvantnim računalništvom. 2006 - številka 1 - letnik XIV upon*«** informatika 33