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, pl. az /etc/passwd fájlt. 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.
Példa 5-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):
Példa 5-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:
Egy jobban átgondolt, tökéletesitett szkript:
Példa 5-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:
Példa 5-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.