Forum und email

Fájlrendszer biztonság

A PHP tiszteli a rendszerbe épített biztonsági megoldásokat, különös tekintettel a fájlok és könyvtárak hozzáférési jogosultságaira. Ez lehetőséget ad arra, hogy megszabd, mely fájlok olvashatóak a rendszerben. A mindenki számára olvasható fájloknál ügyelni kell arra, hogy ne tartalmazzanak olyan fontos adatot, amit nem szabad elolvasnia akármelyik felhasználónak a rendszeren.

Mivel a PHP úgy készült, hogy felhasználói szintű fájlrendszer hozzáférést ad, lehetséges olyan program készítése, amely a rendszerfájlokat olvassa, mint pl. az /etc/passwd fájl, ethernet kapcsolatokat módosít, nagyméretű nyomtatási feladatokat küld, stb. Ez maga után von egy nyilvánvaló következtetést, neveztesen minden esetben meg kell győződni a programokban arról, hogy a helyes fájlokat olvassa illetve írja a program.

Nézzük a következő szkriptet, ahol a felhasználó megadja, hogy le szeretne törölni egy fájlt a könyvtárában. Ez többnyire egy webes felületet jelent, ahol egy PHP program használatos fájlkezelésre, ezért az Apache-t futtató felhasználónak engedélyezni kell a fájlok törlését a felhasználó könyvtárában.

Example#1 A helytelen változó használat ...

<?php
// egy fájl törlése a user könyvtárából
$usernev $_POST["user_altal_beadott_nev"];
$konyvtar "/home/$usernev";
$torlendo_file "$userfile";
unlink ($konyvtar/$torlendo_file);
echo 
"$torlendo_file törölve!";
?>
Mivel a $usernev egy HTML űrlapból érkezik, a felhasználó beírhat tetszőleges felhasználói nevet és fájlnevet, így akár más könyvtárát is manipulálhatja. Ebben az esetben általában valamilyen felhasználó-azonosítási eljárást kell alkalmazni. Lássuk, mi történik, ha a beadott változók a "../etc/" és a "passwd". A kód akkor így alakulna (az adatokat behelyettesítve):

Example#2 ... fájlrendszer támadáshoz vezethet

<?php
// egy fájl törlése akárhonnan, ahol a PHP usernek
// joga van erre. Ha a PHP root userként fut:
$usernev "../etc/"
$konyvtar "/home/../etc/";
$torlendo_file "passwd";
unlink ("/home/../etc/passwd");
echo 
"/home/../etc/passwd törölve!";
?>
Két fontos komponensre kell odafigyelni, hogy megelőzhessük az ilyen problémákat:
  • Csak korlátozott jogok beállítása a PHP-t futtató felhasználónak.
  • Minden felhasználótól bejövő adat ellenőrzése.
Egy jobban átgondolt, tökéletesitett szkript:

Example#3 Biztonságosabb fájl ellenőrzés

<?php
// egy fájl törlése akárhonnan, ahol a PHP usernek
// joga van erre.
$usernev $_SERVER['REMOTE_USER']; // ez a user azonosított neve
                                             // (ha volt előtte azonosítás)

$konyvtar "/home/$usernev";

$torlendo_file basename("$userfile"); // elérési trükközés eldobása
unlink ($konyvtar/$torlendo_file);

$fp fopen("/home/logging/filedelete.log","+a"); // törlés naplózása
$logstring "$usernev $konyvtar $torlendo_file";
fputs ($fp$logstring);
fclose($fp);

echo 
"$torlendo_file törölve!";
?>
Mindamellett, ez sem mentes a hiányosságoktól. Ha az aktuálisan használt hitelesítési módszer (authentication) megengedi a felhasználóknak, hogy saját loginnevet válasszanak, és az egyikük a "../etc/" -t választja, akkor a rendszer ugyanolyan védtelenné válik. Ebből kiindulva a jobban testreszabott ellenőrzés a következőképp alakulna:

Example#4 Biztonságosabb fájlnév-ellenőrzés

<?php
$usernev 
$_SERVER['REMOTE_USER']; // hitelesites
$homedir "/home/$usernev"$homedir "/home/$usernev";

if (!
ereg('^[^./][^/]*$'$userfile))
    die(
'rossz fájlnév'); // vége, nincs feldolgozás

if (!ereg('^[^./][^/]*$'$usernev))
    die(
'rossz usernev'); // vége, nincs feldolgozás
//stb...
?>

A használt operációs rendszertől függően széles a védeni kívánt fájlok skálája, beleértve az eszköz hivatkozásokat (/dev/ vagy COM1), konfigurációs fájlokat (/etc/ és az .ini fájlok), jól ismert tárolóhelyek (/home/, My Documents), stb. E sokaság miatt könnyebb egy olyan rendszert készíteni, ahol mindent tiltunk azon kívül, amelyet kifejezetten megengedünk.