» »

Varnost v PHPju

Dandanes ogromno ljudi uporablja PHP z namenom, da hitro sestavijo svoje dimanično generirane spletne strani. Ob tem seveda nihče ne pomisli na varnost oziroma na pisanje "varne" kode - brez oziroma z malo možnosti vdora in zlorabe strežnika, na katerem so skripte postavljene. Kot prvo je treba imeti v mislih, da v primeru napada zaradi slabo napisane kode ne bomo oškodovani samo mi - sposobni napadalci lahko tako na preprost način poškodujejo celoten sistem. Seveda krivda za slabo napisano kodo ni vedno na strani pisca - napake obstajajo tudi v samem PHPju - zato redno nadgrajujte svoje sisteme, saj vsaka nova verzija odstrani nadležne hrošče in dodatne možnosti vdora. Ta članek predstavi tri najosnovnejše možnosti zlorabe in seveda tudi zaščito.


Vstavljanje kode

Kaj je to vstavljena koda? To je niz znakov, ki jih uporabnik napiše s slabim namonom, da bi vplival na delovanje skripte, baze, itn. Ob slabo napisani kodi lahko dostopa do zaščitenih podatkov, jih briše, popravlja ter vnaša in to brez kakšnega posebnega napora. Če skripte nimamo pravilno napisane, se zna zgoditi, da kdorkoli nebodigatreba to izkoristi in uporabi proti nam. Pa se postavimo na stran napadalca - kako preverimo, če je stran primerno zaščitena? Recimo, da si je avtor zamislil prikaz uporabnikov v stilu:

/uporabniki.php?id=45

Kaj lahko vidmo? Skripta uporabnik najbrž pošlje zahtevek po podatkih uporabnika z IDjem, nastavljenim na vrednost 45. Ker je bil naš domnevni programer brez domišlije, ima nastavljeno ime polja prav tako na "userID". Ker je programer pozabil tudi na pretvarjanje spremenjivk in postavitev narekovajev v SQL stavku, bo tale zloraba preprosta. Če številko 45 zamenjamo z nizom "

46%20or%20userID%3d45
", se lahko zgodita dve možnosti:

  • Avtor je predvidel vdor in poskrbel za filtriranje podatkov - skripta je varna
  • Avtor je malomarno izdelal skripto, brez napak se pokažejo podatki uporabnika 46

Kaj pa "

46%20or%20id%3d45
" sploh pomeni? Pretvorjeno v nam berljivo, prevedeno obliko, ta niz pomeni "46 or userID = 45". Pred seboj imamo v bistvu terminal z neposrednim dostopom do SQL strežnika. Zelo neugodno.

Kako pa se zaščitimo pred takimi vrstami vdorov?

Pri tem konkretnem primeru bi bilo najbolje pretvoriti vrednost userID v celoštevilčno vrednost - integer. Na voljo imamo kar tri načine pretvorbe:

 
$userID = intval($userID);
 
$userID = (int)$userID;
 
settype($userID, 'int');

Prva dva vrneta novo vrednost tipa integer, zadnja pa pretvori spremenjivko v tip integer. Kaj se zgodi z vsebino? Boolean vrednosti (true/false) se pretvorijo v 1 oziroma 0 (false). String vrednosti pa vrnejo 0, razen, če je v stringu (ali na začetku le-tega) številka -- v tem primeru vrne ustrezno številko.

Kaj pa vrednosti, ki niso številke?

Najpametneje je uporabljati funkcije mysql_escape_string(), pg_escape_string() ter addslashes(), ki poskrbijo, da SQL strežnik ne upošteva posebnih znakov, ki bi nam lahko v nasprotnem primeru povzročili sive lase.


Kjerkoli v svoji kodi se sklicujete na neke objekte v sistemu, na primer imena datotek, imena tabel in stolpcev v bazi, je pametno uporabiti nadomestna imena oziroma vnose dobro prefiltrirati, saj nikoli ne vemo, kdaj lahko mimo nas pride kakšna ZlobnaKoda™ - nastala škoda pa je lahko zelo velika.

Prijava zastonj ali register_globals = On


Poznate tole?
 
if ( $_POST["uporabnik"] == "Janez" && $_POST["geslo"] == "micka456" ) {
  $prijava = TRUE;
}
 
if ( $prijava ) {
  // Naredi nekaj, kar lahko naredijo
  // samo prijavljeni uporabniki...
  echo "Prijava uspešna!";
}

Pa poskusite dostopati, neprijavljeni seveda, do strani, ki vsebuje zgornjo kodo takole (predpostavimo da je ime datoteke test.php):

 
test.php?prijava=1

Če se je zgodilo točno tisto, kar se nebi smelo -- izpis "Prijava uspešna!" -- in se s tem podatkom ne strinjate, berite dalje:

Nastavitev register_globals vpliva na način obravnave celotnega spektra uporabniško poslanih podatkov. Vrednost on povzroči to, da se vsem spremenljivkam, poslanim z uporabo metod GET in POST, avtomatično dodeli php spremenljivka z enakim imenom ter vrednostjo. V primeru vrednosti off pa so spremenljivke na katerih vsebino ima vpliv uporabnik temeljito lo&$269;ene od naših.

Kako, prosim?

V tem konretnem primeru je spremenjivka $prijava dobila vrednost 1, brez da bi uporabnik vedel uporabniško ime in geslo. Če imamo register_globals v nastavitvah omogočeno, enako vpliva na vrednosti v piškotkih:

  • $_COOKIE, $HTTP_COOKIE_VARS (PHP < 4.2) 

in na podatke iz obrazca:
  • $_POST, $HTTP_POST_VARS (PHP < 4.2)

Enako velja za SERVER in ENV. Prav tako vpliva na že zgoraj omenjenjene vrednosti podane z metodo GET:
  • test.php?prijava=1 $_GET, $HTTP_GET_VARS (PHP < 4.2)
Enako bi dosegli, če bi naredili naslednje:

 
$prijava = $_GET[&quot;prijava&quot;];
Kako se zaščitimo?

Najbolj preprosto je, če spremenimo vrednost nastavitve register_globals na Off in uporabljamo $_GET, $_POST, $_COOKIE, $_ENV, $_SERVER.

Če uporabljate tak nezanesljiv sistem prijave, je naslednji korak izboljšava le-tega. Takole se še bolje zaščitite, saj spremenjivka $prijava v vsakem primeru dobi neko vrednost.

 
if ( $_POST[&quot;uporabnik&quot;] == &quot;Janez&quot; &amp;&amp; $_POST[&quot;geslo&quot;] == &quot;micka456&quot; ) {
  $prijava = true;
}
else {
  $prijava = false;
}
 
(ali: $prijava = (($_POST[&quot;uporabnik&quot;] == &quot;Janez&quot;) &amp;&amp; ($_POST[&quot;geslo&quot;] == &quot;micka456&quot;)) --Primoz)
 
if ( $prijava == true ) {
  // Naredi nekaj, kar lahko naredijo
  // samo prijavljeni uporabniki...
  echo "Prijava uspe&#353;na!";
}

Možnost register_globals je od verzije 4.2.0 naprej kot privzeto izklopljena - najpametneje jo je pustiti tako, saj s tem dobimo malo večji nadzor nad tem, kaj se dogaja z našimi spremenjivkami.


Rokovanje z datotekami

Večkrat se nam zgodi, da pozabimo na pravice in poganjamo svoj spletni strežnik (apache) kar kot root uporabnik (linux sistem seveda) (to je danes skoraj nemogoče, saj je potrebno kar precej dela da se apača prepriča da ne stori samomora v tem primeru --Primoz). To omogoča uporabnikom dostop do datotek, ki jim niso namenjene (to se lahko zgodi tudi če strežnik ne deluje z administratorskimi pravicami --Primoz). Kaj se lahko zgodi? Preprost del kode se lahko obrne proti nam samim.

include $_GET[&quot;datoteka&quot;];

Z malo truda se v tem primeru lahko dokopljemo do vsake (skoraj --Primoz) datoteke na strežniku.

Kako se zaščitimo?

Kot prvo moramo določiti uporabnika z minimalnimi pravicami (branje, mogoče tudi pisanje, če je to potrebno) do datotek, ki jih bomo prikazovali obiskovalcem. S tem avtomatično zapremo dostop do vseh ostalih lokacij na disku in smo že en korak bližje varnejšemu izdelku.

Naslednji korak je filtriranje vnešenih podatkov. Tu takega pristopa kot v prvem poglavju ne moremo uporabiti. Preprost trik, ki ga lahko uporabimo, je zamenjava imen datotek z drugim nizom:

switch ( $_GET[&quot;datoteka&quot;] ) {
 
  case &quot;clanki&quot;:
    include &quot;clanki.html&quot;;
    break;
  case &quot;info&quot;:
    include &quot;info.html&quot;;
 
    break;
  default:
    include &quot;napaka.html&quot;;
    break;
 
}

Če vam zgornja rešitev ne odgovarja (zaradi vključitve prevelikega števila daototek), priporočam da dano spremenjivko z imenom datoteke čim bolj filtrirate - na primer z uporabo funkcije basename(), ki vrne ime datoteke brez poti, z določanjem kočnice datoteke in z absolutno (ne relativno) potjo do datoteke.


Zaključek

Možnih načinov vdora je še veliko, nekaj ste jih nabrž po naključju tudi že sami odkrili. Nobene stvari, ne operacijskega sistema, ne vašga spletnega programa ni možno v celoti zaščititi, ampak z nekaj preprostimi ukrepi, kot so tej našteti zgoraj, lahko preprečimo najosnovnejše načine zlorabe. Ob vsakem vnosu podatkov s strani uporabnika natančno preverite ta vnos, če je res takšen, kar od njega pričakujete. Številke so številke, tekst je tekst brez nepotrebnih znakov, ki bi lahko škodovali bazi podatkov.

Šifriranje nosilcev podatkov v okolju Linux in Windows

Šifriranje nosilcev podatkov v okolju Linux in Windows

Cryptography is a data-protection technology just as gloves are a hand-protection technology. Cryptography protects data from hackers, corporate spies and con artists, whereas gloves protect hands from cuts, scrapes, heat, cold and infection. The former can frustrate FBI wiretapping, and the latter can ...

Preberi cel članek »

Spam, spam, spam

Spam, spam, spam

Oglaševanje in propagiranje raznovrstnih izdelkov nas spremlja že dolgo časa. Reklame na televiziji ter radiu, gigantski posterji ob cestah, deljenje reklamnih letakov in njihovo zatikanje v poštne nabiralnike so le najbolj tipični predstavniki oglaševanja, ki smo se ga ...

Preberi cel članek »

Sed

Sed

Velika količina podatkov je in še dolgo bo v tekstovni obliki. HTML, XML, /etc/passwd in večina drugih konfiguracijskih datotek, celotna linux dokumentacija, PDF in DOC (bolj ali manj), mnoge knjige in sodbe sodišč, dolgočasni samoupravni sporazumi. V tem in še enem ...

Preberi cel članek »