Validace vstupních parametrů

Uživatelské vstupy do systému i výstupy ze systému jsou kritickým místem každé aplikace. Většina úspěšných útoků totiž souvisí právě s vhodně formulovanými a zaslanými parametry [20]. Validace vstupů a výstupů je tedy z hlediska celkové bezpečnosti webové aplikace naprosto klíčová.

Způsob validace je úzce spojený s celkovou architekturou aplikace. Volba vhodných validačních strategií a určení aplikační architektury by proto měly být prováděny zároveň v úvodních fázích projektu. Ideální je použití jednotné komponenty, která dle zadaných pravidel filtruje všechny vstupy i výstupy.

Testovat se podle [20] vždy musí zejména typ dat, jejich syntaxe a délka. U jazyků striktně rozlišujících datové typy (například C/C++) by chybný typ dat mohl způsobit chybnou interpretaci obsahu proměnné, její přetečení apod. U typově benevolentnějších jazyků (například PHP) zase může dojít k neočekávaným chováním v důsledku implicitních přetypování. Kontrola syntaxe vyloučí nepovolený obsah vstupů, například vstřik SQL příkazu. A v neposlední řadě, test povolené délky parametrů zabrání zejména pokusům o přetečení proměnné a následné přepsání výkonné části aplikace.

[20] uvádí tři základní modely, mezi kterými si lze vybrat při implementaci validace parametrů:

Povolit pouze známá validní data

Aplikace by měla přijímat jen a pouze parametry, které jsou známé, bezpečné a očekávané. Například při vstupu rodného čísla bez lomítka akceptuje pouze devítimístné či desetimístné celé číslo, které neobsahuje žádné jiné znaky, než číslice, a je navíc dělitelné jedenácti. Všechny ostatní vstupy se jako potenciálně nebezpečné zahazují. Jedná se o doporučovanou a široce používanou strategii.

Zakázat známá chybná data

Tato strategie je založena na předpokladu, že aplikace zná vzory všech vstupů, které jsou nebezpečné. Takové vstupy tedy dokáže rozeznat a zahodit, zatímco všechny ostatní postoupí do dalšího zpracování. Například při vstupu textu, který se později bude vypisovat jako součást webové stránky (třeba vzkaz v knize hostů) systém mimo jiným kontroluje i to, zda parametr neobsahuje tag <script>, kterým by se útočník snažil ovlivnit výpis výsledné stránky. Je zřejmé, že je velice obtížné (až nemožné) dát dohromady aktuální seznam všech typů nebezpečných vstupů, zejména u složitějších aplikací.

Opravit všechna data

Při vstupní kontrole se pokoušíme chybná data opravit do bezproblémové podoby. Například při již zmíněném zpracování nového vzkazu do knihy hostů odstraní aplikace z textu všechny případné tagy kromě několika explicitně povolených (typicky <strong>, <em> apod.). Tuto strategii je vhodné využívat až v druhé řadě, zejména v kombinaci s některým z předchozích dvou přístupů.

Validace vstupních parametrů by měla v každém případě vždy probíhat na straně serveru pod plnou kontrolou aplikace. Samozřejmě lze implementovat i kontrolu odesílaných dat na straně klienta, typicky JavaScriptovým kódem ve stránce. Ale pouze jako redundantní doplněk k serverové kontrole, který zvyšuje pohodlí uživatele. Nelze se však na něj vůbec spoléhat, jakoukoliv kontrolu probíhající v prohlížeči lze totiž obejít či vypnout. Útočník dokonce vůbec nemusí používat prohlížeč, své HTTP požadavky může zasílat serveru přímo, třeba prostřednictvím nějakého skriptu či telnetu.

PHP samo o sobě provádí jen omezenou kontrolu a zpracování vstupních parametrů. Pokročilé možnosti validace ale nabízí snad každý framework, samozřejmě s ohledem na svou architekturu a postup zpracování požadavku. Z některých vlastností samotného PHP ale vyplývají potenciální bezpečnostní rizika. Jedná se zejména o automatickou registraci všech parametrů jako globálních proměnných stejného jména. Ty v závislosti na konfiguraci mohou přepisovat i některé systémové proměnné. Jako příklad uvádí [12] následující kód, který nejprve na základě zaslaných parametrů user a pass autentizuje uživatele. Následně pak na základě toho autorizuje zobrazení citlivých dat.

<?php
if (Validate_User($user$pass)) {
    
$authorized 1;
}

// nějaký případný další kód...

if ($authorized) {
    
Display_Secret_Data();
}
?>

Uvedený kód je zcela chybný. Citlivá data totiž zobrazí i v případě, že příslušnou stránku otevřeme sice bez uvedení správného uživatelského jména a hesla, ale s nastavenou hodnotou proměnné $authorized, například přes volání http://www.example.com/mypage.php?authorized=1. Jedním z možných řešení je na samém začátku skriptu přiřadit proměnné $authorized nulovou hodnotu. Další možností je nastavit v konfiguraci PHP direktivu register_globals=off, která zakáže automatické přiřazování obdržených parametrů do globálních proměnných. K parametrům pak lze přistupovat přes superglobální pole $_GET, $_POST$_REQUEST.