PHP je stejně jako většina projektů s otevřeným zdrojovým kódem poměrně bezpečné. Díky otevřenému kódu si s vynaložením určitého úsilí může každý ověřit, jestli v jazyce nejsou otevřená nějaká zadní vrátka nebo se v něm neskrývají jiné bezpečnostní hrozby. Nebo se dá zkrátka věřit tomu, že těch několik desítek lidí, kteří se ve zdrojáku jazyka PHP vyznají a sledují všechny změny, si vzájemně nekryje záda. Díky otevřenému kódu je také obvykle mnohem rychlejší vydávání bezpečnostních záplat.
Úzké hrdlo bezpečnosti serveru tedy obvykle netkví přímo v PHP, ale spíše v nastavení přístupových práv, obzvláště na serverech s více uživateli. Abych to trochu vysvětlil, je nutné nejprve potřeba stručně popsat, jak to na serverech s více uživateli vypadá. Jednotliví uživatelé obvykle dostanou vlastní přístupové údaje, pomocí kterých si na server nahrávají své soubory. Zobrazování souborů na webu zajišťuje webový server, který obvykle běží pod vyhrazeným uživatelem (platí např. pokud je PHP použito jako modul Apache). Aby soubory mohly být zobrazeny, musí mít tento uživatel právo jejich čtení. A v tom tkví bezpečnostní riziko – když se pod tímto uživatelem provede jakýkoliv kód, má práva čtení všech souborů zobrazovaných na webu. Může si tedy např. přečíst zdrojové kódy ostatních webů, přístupové údaje a cokoliv dalšího ho napadne.
Přestože se tento problém netýká přímo PHP (úplně stejný problém nastane i při použití jiných skriptovacích technologií, takže by měl být řešen spíše na úrovni webového serveru), nabízí proti němu PHP poměrně účinnou obranu. Direktiva open_basedir slouží k zamezení přístupu mimo zadaný adresář. Pokud tuto direktivu správně nastavíme např. pro každou doménu, máme skoro vyhráno. „Skoro“ píšu proto, že PHP samo o sobě nezaručuje, že všechna rozšíření budou tuto direktivu respektovat – nicméně pokud používáme pouze ta standardně dodávaná, spolehnout se na to v podstatě dá. Poslední problém tak zůstává u funkcí pro spouštění příkazů systému jako je např. exec. Ty buď můžeme zakázat direktivou disable_functions nebo spolu s dalšími omezeními omezit direktivou safe_mode.
Na některých hostinzích je zapnuta jenom direktiva safe_mode a jejich správci žijí v přesvědčení, že je jejich server neprůstřelný. Tato direktiva mimo jiné ověřuje, jestli vlastník načítaného souboru odpovídá vlastníkovi spuštěného skriptu. Nic nám ale nebrání si vlastním skriptem vytvořit jiný skript – ten už bude patřit uživateli, pod kterým běží webový server, takže z něj následně bude možné přečíst všechny stejně vytvořené soubory – např. soubory se session nebo veškerá data nahraná na server PHP skriptem a uložená do souborů.
<?php // skript bad_code2.php bude patřit uživateli, pod kterým běží webový server copy("bad_code.php", "bad_code2.php"); // tímto skriptem si např. můžeme přečíst všechny soubory s uloženými session $session_path = preg_replace('~.*;~', '', ini_get("session.save_path")); foreach (glob(($session_path ? $session_path : $_ENV["TEMP"]) . "/sess_*") as $filename) { echo "$filename\t"; readfile($filename); echo "\n"; } ?>
Pokud tedy provozujete webový server, na který má přístup více uživatelů, tak alespoň správně nastavte obě direktivy – open_basedir a buď safe_mode nebo disable_functions. Zamezit získání názvů session proměnných je nejlepší přímo na úrovni operačního systému – stačí adresář session.save_path učinit nečitelný pro uživatele, pod kterým běží webový server (a pokud mají na server přístup i běžní uživatelé, tak samozřejmě i pro ně). Tento uživatel pak bude moci v adresáři číst a zapisovat soubory, ale nepodaří se mu získat jejich seznam.
Na tom se ostatně bezpečnost webového serveru dá také vystavět – stačí weby jednotlivých uživatelů umístit do adresářů neuhodnutelného jména, nadřazenému adresáři sebrat právo čtení a obejdete se bez open_basedir i safe_mode. Pokud si ale uživatel zapne direktivu display_errors, tak si při chybě skutečný adresář ukáže – i proto je dobré mít tuto direktivou na ostrém webu vypnutou.
Podotýkám, že tento text se vztahuje k bezpečnosti webového serveru jako takového. Další důležitou oblastí je zabezpečení webové aplikace, kde toho v PHP jde zkazit ale také samozřejmě ošetřit většinu.
Přijďte si o tomto tématu popovídat na školení Bezpečnost PHP aplikací.
Diskuse je zrušena z důvodu spamu.