Forum und email
Bezpečnost souborových systémů

Kapitola 26. Bezpečnost souborových systémů

PHP pracuje se zabezpečením zabudovaným do většiny serverových systémů, které je založeno na oprávněních k souborům a adresářům. To vám umožňuje ovládat, které soubory v souborovém systému se smí číst. Pozornost je potřeba věnovat jakýmkoli souborům, které jsou čitelné všem uživatelům, kvůli tomu, zda je skutečně bezpečné, aby je směli číst všichni uživatelé, kteří mají k tomuto systému přístup.

Jelikož je PHP navrženo tak, aby umožňovalo přístup k filesystému na úrovni uživatele, je vcelku možné napsat PHP skript, který vám umožní číst systémové soubory, jako např. /etc/passwd, měnit konfiguraci ethernetu, posílat na tiskárnu obrovské tiskové úlohy apod. To má jasné důsledky v tom, že se musíte vždy ujistit, že soubory, které chcete číst nebo zapisovat, jsou skutečně ty správné.

Uvažujme následující skript, kde uživatel říká, že by chtěl smazat soubor ve svém domovském adresáři. To předpokládá situaci, kde se pro normální správu souborů používá webové rozhraní implementované pomocí PHP, a uživatel, pod nímž běží Apache, má právo mazat soubory v domovských adresářích uživatelů.

Příklad 26-1. Slabá kontrola proměnných vede k....

<?php
// odstraň soubor z domovského adresáře uživatele
$username = $_POST['user_submitted_name'];
$homedir = "/home/$username";
$file_to_delete = "$userfile";
unlink ("$homedir/$userfile");
echo
"$file_to_delete byl smazán!";
?>
Jelikož se uživatelské jméno posílá z formuláře, může kdokoli poslat uživatelské jméno a soubor patřící někomu jinému a mazat cizí soubory. V takovém případě byste měli chtít používat nějakou formu autentizace. Uvažte, co by se mohlo stát, kdyby poslané proměnné obsahovaly "../etc/" a "passwd". Kód by pak mohl bez problémů číst:

Příklad 26-2. ...útoku na souborový systém

<?php
// Odstraní soubor odkudkoli na pevném disku, kam má uživatel PHP přístup.
// Má-li PHP rootovská práva:
$username = "../etc/";
$homedir = "/home/../etc/";
$file_to_delete = "passwd";
unlink ("/home/../etc/passwd");
echo
"/home/../etc/passwd byl smazán!";
?>
Existují dvě důležité roviny, ve kterých byste se měli těmto problémům bránit.

  • Povolit programu PHP pouze omezená oprávnění.

  • Kontrolovat všechny zasílané proměnné.

Zde je vylepšený skript:

Příklad 26-3. Bezpečnější kontrola názvu souboru

<?php
// Odstraní soubor z pevného disku, kam má uživatel PHP přístup.
$username = $_SERVER['REMOTE_USER']; // použití autentizačního mechanismu

$homedir = "/home/$username";

$file_to_delete = basename("$userfile"); // odřízni cestu
unlink ($homedir/$file_to_delete);

$fp = fopen("/home/logging/filedelete.log","+a"); // zaznamenej smazání
$logstring = "$username $homedir $file_to_delete";
fwrite ($fp, $logstring);
fclose($fp);

echo
"$file_to_delete byl smazán!";
?>
Ovšem ani toto není zcela neprůstřelné. Pokud by váš autentizační systém povoloval uživatelům vytvářet si vlastní uživatelská jména, a uživatel by si vybral "../etc/", systém by byl opět ohrožen. Z tohoto důvodu byste měli preferovat lépe přizpůsobenou kontrolu:

Příklad 26-4. Bezpečnější kontrola názvu souboru

<?php
$username
= $_SERVER['REMOTE_USER']; // použití autentizačního mechanismu
$homedir = "/home/$username";

if (!
ereg('^[^./][^/]*$', $userfile))
     die(
'bad filename'); // skonči, nezpracovávej

if (!ereg('^[^./][^/]*$', $username))
     die(
'bad username'); // skonči, nezpracovávej
// atd...
?>

V závislosti na operačním systému existuje celá široká škála souborů, o které bychom se měli zajímat, včetně souborů zařízení (/dev/ nebo COM1), konfiguračních souborů (soubory /etc/ a .ini), známé oblasti ukládání souborů (/home/, Dokumenty) atd. Proto je obvykle lepší ustanovit politiku, kde je zakázáno všechno kromě toho, co explicitně povolíte.