Bezpečnost především – vyhněte se script injection

26. července 2002

Už na úrovni klienta je možné provést některé kontroly pomocí JavaScriptu, které testují, zda uživatel vyplnil správné a adekvátní údaje. Tyto kontroly jsou ale jen důležitým „kosmetickým“ doplňkem. Pokud chce někdo „nabourat“ vaši aplikaci, jsou neúčinné. Metodě, kdy někdo podvrhne falešné nebo nebezpečné parametry aplikaci, říkáme „script injection“.

Když skript spouští nějaký externí program a jako parametry mu předáváte data vložená uživatelem, můžete vytvořit velmi nebezpečnou aplikaci. Je naprosto nutné provést kontrolu vložených dat, zda obsahují to, co předpokládáte. Například budete chtít provést exec"man $cmd";. Uživatel vloží do formuláře hledaný řetězec, například „ls“, a do stránky se vypíše nápověda k povelu ls. Když ale někdo zadá například "ls; rm *", může smazat některé soubory. Jiným zadáním si může nechat třeba vypsat soubor s hesly /etc/passwd. Tomuto lze zabránit vhodnou konfigurací serveru, ovšem primárně je nutné vždy provést kontrolu přímo ve skriptu – minimálně odstranit speciální znaky, jako je středník nebo dolar a nahradit je escape sekvencemi (; $). K tomu v PHP slouží funkce EscapeShellCmd.

$cmd=EscapeShellCmd($cmd);

Zde je potřeba zmínit, že kdysi velká výhoda PHP, kdy je lhostejné, zda jsou data zadána metodou GET nebo POST, protože PHP jejich hodnoty nastaví do proměnných odpovídajících předávanému názvu parametru, je v dnešní době (od PHP verze 4.1+) již považována za potenciálně nebezpečnou a ve výchozím nastavení je vypnuta (register_globals=off). Řada bezpečnostních problémů může pak vyvstat z toho, že někdo v URL podvrhne proměnnou, která by jinak vznikla za běhu skriptu například korektním přihlášením a uložením do session, ale jsou možné i jiné způsoby zneužití (vysvětlíme si dále). Proto silně doporučuji v nových skriptech používat zásadně tento přístup k parametrům:

$_GET[„var1“] // pro parametr var1 předaný metodou GET
$_POST[„var2“] // pro var2 předaný metodou POST
$_SESSION[„var3“] // pro proměnou var3, která je součástí session

V předchozích verzích je možno použít $HTTP_POST_VARS[„var“], $HTTP_GET_VARS[„var“].

V některých případech (například pokud máme proměnnou, která se uloží do session a udává id přihlášeného uživatele) je nutno otestovat, zda někdo proměnnou nepodvrhl:

if (($var1==$HTTP_POST_VARS[„var1“]) ||($var1==$HTTP_GET_VARS[„var1“])) { // test, zda proměnná $var1 nebyla podvržena metodou GET nebo POST
  header („Location: http://……./n“); // přesměrovat na hlavní stránku při pokusu o narušení aplikace
  exit;
}

Nejjistější je použít nastavení PHP register_globals=off, tak se proměnné odpovídající předávaným parametrům vůbec neinicializují a je po problému. Nutno poznamenat, že v tomto ohledu je poněkud ukecané ASP oproti starším verzím PHP ve výhodě, protože ani začátečníkovi neumožní vytvořit takto „děravou“ aplikaci. Každou proměnnou je nutno inicializovat, předávané parametry se do proměnné načtou podle typu metody, k podvrhu zde tedy nemůže dojít:

Dim var1, var2 // inicializace proměnných var1, var2
var1 = Request.Form(„par1“) // do proměnné var1 je předána hodnota parametru par1 předávaného metodou POST
var2 = Request.QueryString(„par2“) // do proměnné var2 je předána hodnota parametru par2 předávaného metodou GET

Jedním z případů podvržení proměnné v URL může být situace, kdy je testován referer. Stačí zadat požadované URL a přidat proměnnou $HTTP_REFERER. Pokud totiž zadáváte adresu přímo do nově otevřeného okna, prohlížeč tuto položku vůbec neposílá (není k dispozici), a PHP ji tedy nenastavuje. Pokud ale nastaví proměnné z URL, jednoduše zaměníte vaši proměnnou za položku z hlavičky. Můžete tak použít třeba vlastní formulář pro službu, která si špatně hlídá, zda ji někdo volá z určité stránky, ovšem následky mohou být ještě horší. Někdy se jako doplňujícího ověřovacího prvku k $REMOTE_ADDR využívá položka z hlavičky „$HTTP_X_FORWARDED_FOR“. Tu může nastavovat proxy a obsahuje skutečnou IP adresu stroje, pro který se požadavek vyřizuje. V praxi se můžeme setkat s „důmyslně“ neuvěřitelnými konstrukcemi, kdy je ochrana založená na IP adrese, ale pokud je zadaná položka „$HTTP_X_FORWARDED_FOR“, použije se místo ní, což znamená, že takové ochraně hravě změníte svoji IP adresu prostě tak, že podstrčíte tuhle položku! Můžete tak násobně hlasovat v anketě, ale jistě by se našel i případ, kdy dílo zkázy bude mnohem horší.

Tato problematika je složitější, proto se jí budu věnovat ještě v přespříštím díle – jde o metody zcizení session a získání přístupu pod cizí identitou (session steal). V příštím díle nejprve „odbočíme“ k bezpečnostním problémům při práci s databází prostřednictvím SQL, protože toto také souvisí s metodami podvržení nebezpečných znaků a sekvencí přes parametry POST nebo GET (již zmíněný script injection).

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *