Vodič za PHP bezbednost (PHP Security Guide): Baze podataka i SQL


< PreviousNext >SesijeProcesuiranje formulara

Otkrivene podaci pristupa

Većina PHP aplikacija komuniciraju sa bazom podataka. Ovo obično uključuje povezivanje na server baze podataka i korišćenje podataka pristupa za potvrdu autentičnosti:

<?php

$host = 'example.org';
$username = 'myuser';
$password = 'mypass';

$db = mysql_connect($host, $username, $password);

?>

Ovo bi mogao biti primer fajla po imenu db.inc koji je priključen kada god je povezivanje sa bazom potrebno. Ovaj pristup je zgodan, i drži podatke pristupa u jednom fajlu.

Potencijalni problemi nastaju kada je ovaj fajl lociran unutar korena (root-a) dokumenta. Ovo je uobičajeni pristup, zato što čini include i require naredbe mnogo jednostavnijim, ali može dovesti do situacija koje mogu prikazati vaše podatke pristupa.

Zapamtite da sve unutar korena dokumenta ima URL povezan sa sobom. Na primer, ako je koren dokumenta /usr/local/apache/htdocs, onda fajl lociran u /usr/local/apache/htdocs/inc/db.inc ima URL poput http://example.org/inc/db.inc.

Kombinujte ovo sa činjenicom da će većina web servera prikazati .inc fajlove kao plaintext fajlove, i rizik od prikazivanja vaših podataka pristupa treba da je jasan. Veći problem je bilo koji izvorni kod u ovim modulima može biti izložen, ali podaci pristupa su posebno osetljivi.

Naravno, jedno prosto rešenje je da izmestite sve module izvan korena dokumenta, i ovo je dobra praksa. I include i require mogu da prihvate fajl sistemsku putanju, pa ne postoji potreba da se ovi moduli učine dostupnim preko URL-a. To je nepotrebni rizik.

Ako nemate drugog izbora za smeštanje vaših modula, i oni moraju biti unutar korena dokumenta, možete staviti nešto poput ovoga u vaš httpd.conf fajl (pretpostavljajući da je u pitanju Apache web server):

<Files ~ "\.inc$">
    Order allow,deny
    Deny from all
</Files>

Nije dobra ideja da procesuirate svoje module PHP endžinom. Ovo uključuje preimenovanje vaših modula sa .php ekstenzijom kao i korišćenje AddType da sadrži .inc fajlove tretirane kao PHP fajlove. Izvršavanje koda van konteksta može biti veoma opasno, jer je nepredviđeno i može voditi ka nepoznatim rezultatima. Međutim, ako se vaši moduli sastoje od dodeljivanja varijabli (kao u primeru), ovaj rizik je umanjen.

Moj omiljeni metod za zaštitu podataka pristupa bazi podataka je opisan u knjizi PHP kuvar (PHP Cookbook O'Reilly) od strane David-a Sklar-a i Adam-a Trachtenberg-a. Kreirajte fajl, /path/to/secret-stuff, koji samo root korisnik može da čita (ne nobody):

SetEnv DB_USER "myuser"
SetEnv DB_PASS "mypass"

Priključite ovaj fajl u httpd.conf kao što sledi:

Include "/path/to/secret-stuff"

Sada možete da koristite $_SERVER['DB_USER'] i $_SERVER['DB_PASS'] u vašem kodu. Ne samo da nikad nećete morati da pišete svoje korisničko ime i šifru u bilo kom vašem skriptu, web server ne može da čita secret-stuff fajl, tako da ni jedan drugi korisnik ne može da napiše skript koji čita vaše podatke pristupa (bez obzira na jezik). Samo budite pažljivi da ne prikazujete ove promenljive sa nečim kao phpinfo() ili print_r($_SERVER).

SQL ubacivanje (SQL Injection)

Od napada SQL ubacivanjem jako se jednostavno odbraniti, alo mnoge aplikacije su još uvek ranjive. Razmotrite sledeću SQL naredbu:

<?php

$sql = "INSERT
        INTO   users (reg_username,
                      reg_password,
                      reg_email)
        VALUES ('{$_POST['reg_username']}',
                '$reg_password',
                '{$_POST['reg_email']}')";

?>

Ovaj upit je konstruisan sa $_POST, što bi odmah trebalo da izgleda sumnjivo.

Pretpostavite da ovaj upit pravi novi nalog. Korisnik obezbeđuje željeno korisničko ime i email adresu. Registraciona aplikacija generiše privremenu šifru i šalje je korisniku da potvrdi email adresu. Zamislite da korisnik unese sledeće kao korisničko ime:

bad_guy', 'mypass', ''), ('good_guy

Ovo svakako ne izgleda kao validno korisničko ime, ali kada nema filtriranja podataka, aplikacija to ne može shvatiti. Ako je data ispravna email adresa (shiflett@php.net, na primer), i 1234 je šta aplikacija generiše kao šifru, SQL naredba postaje kako sledi:


<?php

$sql = "INSERT
        INTO   users (reg_username,
                      reg_password,
                      reg_email)
        VALUES ('bad_guy', 'mypass', ''), ('good_guy',
                '1234',
                'shiflett@php.net')"; ?>

Umesto željene akcije kreiranja jednog naloga (good_guy) sa ispravnom email adresom, aplikacija je prevarena da napravi dva naloga, i korisniku su poslati svi detalji bad_guy naloga.

Dok ovaj primer ne mora da izgleda opasan, treba biti jasno da se mnogo gore stvari mogu dogoditi jednom kada napadač može izmeniti vašu SQL naredbu.

Na primer, u zavisnosti od baze podataka koju koristite, može biti moguće da pošalje višestruke upite serveru baze podataka u jednom pozivu. Tako, korisnik može potencijalno da završi postojeći upit sa tačkom i zarezom i da nastavi sa upitom od izbora korisnika.

MySQL, do nedavno, nije dozvoljvao višestruke upite, tako da je ovaj određeni rizik umanjen. Novije verzije MySQL-a dozvoljavaju višestruke upite, ali sa odgovarajuća PHP ekstenzija (ext/mysqli) zahteva da koristite posebnu funkciju ako želite da pošaljete višestruke upite (mysqli_multi_query() umesto mysqli_query()). Dozvoljavajući samo jedan upit je bezbednije, zato što ograničava šta napadač potencijalno može da uradi.

Zaštita od SQL ubacivanja je laka:

  • Filtrirajte vaše podatke.

    Ovo ne može biti prenaglašeno. Sa dobrim fitriranjem podataka, većina bezbednosnih briga je umanjeno, i neke su praktično eliminisane.

  • Navodite svoje podatke.

    Ako vaša baza podataka dozvoljava (MySQL dozvoljava), stavite jednostruke navodnike oko svih podataka u vašim SQL naredbama, bez obzira na tip podataka.

  • Escape-ujte vaše podatke.

    Nekad ispravni podaci mogu slučajno omesti format SQL naredbe po sebi. Koristite mysql_escape_string() ili funkciju za escaping vaše specifične baze podataka. Ako nema posebne, addslashes() je dobar poslednji izbor.


< PreviousNext >SesijeProcesuiranje formulara