Často sa môže stať, že chceme k stránke pripojiť súbor, ktorý máme uložený na disku niekde inde. Ak zadáme jeho presný názov priamo do funkcie attach, nemusíme sa ničoho obávať.
include 'menu.html';
Predchádzajúci zápis je úplne bezpečný, pretože vždy pripájame ten istý súbor. V tomto prípade nemôže dôjsť k bezpečnostnej chybe. Jediným problémom, ktorý môže nastať, je absencia súboru menu.html, čo vyvolá varovnú správu (ktorá sa pravdepodobne aj tak nezobrazí), ale táto situácia je zriedkavá, pretože zvyčajne pripájame súbor, ktorého existencia je prakticky istá.
Ale čo ak chceme napríklad pripojiť články k jednoduchému webu s obsahom, ako je tento? Na tejto stránke mám fyzický priečinok, kde sú články uložené vo formáte HTML a pripájam ich priamo k zdrojovému kódu.
Samotné pripojenie však nestačí! Začiatočník môže takto nazývať jednotlivé články:
include 'articles/' . $_GET["clanek] . '.html';
Je to však veľmi nebezpečné. Útočník môže odovzdať odkaz na iný adresár pomocou
../
alebo niečoho podobného ako názov článku a niekedy je možné zbaviť sa koncovky odovzdaním nulového bajtu na konci. Mali by ste použiť aspoň funkciubasename()
, ale lepšie je povoliť len hodnoty z bieleho zoznamu.
Často nám nevadí načítanie nesprávneho (neočakávaného) súboru - je to chyba používateľa, ktorý si vyžiadal stránku, ktorú v skutočnosti nechcel, ale môžu nastať situácie, keď to má význam. Najmä:
Ak nemáme možnosť overiť vstup nejakým bezpečným spôsobom (napr. z whitelistu), nemali by sme sa spoliehať na poctivosť používateľa a brániť skripty aspoň na úrovni PHP.
Prvou dôležitou vecou je umiestniť všetky načítané súbory do rovnakého priečinka (adresára) a zakázať niektoré nebezpečné znaky, najmä lomítko a bodku. Tým sa znemožní prístup k iným priečinkom, ktoré obsahujú potenciálne zraniteľné súbory. Nebezpečné znaky možno zakázať aj jednoduchým odstránením zo vstupného reťazca.
$load = '../index'; // tento vstup môže byť potenciálne nebezpečný$load = strtr($load, './', ''); // odstráni všetky bodky a lomítka z reťazcainclude $load .'.html';
Je dôležité poznamenať, že konštrukcia include vykonáva súbory po pripojení rovnakým spôsobom, ako keby išlo o kód PHP, preto je dobré túto možnosť umožniť.
Často však pripájame súbory, ktoré sa nemusia následne vykonať, a zaujíma nás len uložený text (obsah) vo forme reťazca. Preto môžeme súbor načítať do premennej a pracovať s ním ako s reťazcom, čo je celkom bezpečné.
$load = '../index'; // tento vstup môže byť potenciálne nebezpečný$load = strtr($load, './', ''); // odstráni všetky bodky a lomítka z reťazca$file = file_get_contents($load . '.html'); // načítanie obsahu do premennejecho $file; // výpis obsahu súboru
Toto riešenie vyzerá na prvý pohľad zaujímavo a bezpečne - a bezpečné aj je. Aj keď sa používateľovi podarí zavolať súbor PHP, nikdy sa nespustí. Môže ho však zobraziť (teda jeho zdrojový kód) a na to si musíme dať pozor.
Neexistuje na to žiadna definitívna príručka, každý si to musí urobiť sám podľa potrieb scenára. Článok od iných súborov rozpoznám napríklad podľa toho, že obsahujú nadpis veľkosti H1. Ak teda niekto načíta súbor, v ktorom nie je žiadny nadpis, nezobrazím nič a stránka sa skončí chybovou správou. Vždy je dôležité nájsť nejakú jedinečnú vlastnosť, ktorú majú len požadované súbory a ktorú ostatné súbory nemajú, a potom môžete pokračovať.
Hoci je validácia a načítanie súborov pomerne jednoduché, veľké množstvo začiatočníkov stále robí chyby - a bude ich robiť aj naďalej. Najdôležitejšie je správne pochopiť význam toho, čo načítavame, a odlíšiť požadovaný obsah od ostatného. A čo je najdôležitejšie, pracujte s obsahom ako s reťazcom a nikdy ho nenahrávajte priamo do stránky.
Jan Barášek Více o autorovi
Autor článku pracuje jako seniorní vývojář a software architekt v Praze. Navrhuje a spravuje velké webové aplikace, které znáte a používáte. Od roku 2009 nabral bohaté zkušenosti, které tímto webem předává dál.
Rád vám pomůžu:
Články píše Jan Barášek © 2009-2024 | Kontakt | Mapa webu
Status | Aktualizováno: ... | sk