Web může být nebezpečnější, než se zdá

Bezpečnost internetové komunikace je téma, o kterém se stále hodně mluví v nejrůznějších souvislostech. Ať už jde...


Bezpečnost internetové komunikace je téma, o kterém se stále hodně mluví v
nejrůznějších souvislostech. Ať už jde o přenos nešifrovaných e-mailů,
virtuální privátní sítě, nejrůznější červy nebo nezabezpečené webové servery. V
následujícím textu se podrobněji podíváme na úskalí webové komunikace.
Komunikace klienta s webovým serverem probíhá skrze požadavky a odpovědi
protokolu HTTP (HyperText Transfer Protocol). Základní částí syntaxe požadavku
je řetězec, který udává URL souboru, na který se klient dotazuje. Pokud chce
klient serveru sdělit cokoliv jiného, má na výběr několik možností. Údaje,
které jsou standardizované (např. akceptovatelné jazyky, metoda komprese
apod.), se uvádějí v HTTP hlavičce. Jednoúčelová data se dají buď přidat za
otazník do URL souboru (např. GET index.php?Name=Michal) nebo, typicky data z
formuláře, poslat metodou POST. Posledním kanálem, který se dá ke komunikaci
mezi serverem a klientem použít, jsou takzvané cookies. Jsou to proměnné s
relativně krátkými hodnotami, které se posílají oběma směry. Server nastaví
cookie v HTTP odpovědi, klient si ho pamatuje, a pokud se kdykoliv poté
dotazuje na stránku ze stejné domény, hodnotu cookie automaticky pošle. Každé
cookie má svoje vlastní parametry, vedle zmiňované domény je to například
časová platnost. Pokud je nastavena (tzv. permanentní cookies), údaj se po
danou dobu uschovává na disku klienta, v opačném případě jde o druh cookies s
platností pro jeden běh prohlížeče.

Sessions
Sled interakcí mezi webovým serverem a klientem, při kterém server poznává
stálou identitu klienta, nazýváme session. Server mezi interakcemi v rámci
session zpravidla uschovává proměnné vázané na identitu klienta. Každá session
je charakteristická svým založením (při něm server vydá klientovi jednoznačný
identifikátor), svým během (při něm se klient serveru identifikátorem hlásí) a
koncem. Ten může nastat např. zrušením session při odlogování uživatele z
webové aplikace nebo při vypršení stanoveného času.
Ukažme si praktický příklad na imaginárním webovém portálu, který nabízí
vyhledávací katalog stránek a webovou aplikaci pro čtení pošty (např.
freemail). Pokud uživatel prochází odkazy a vyhledává stránky, není obvykle
potřeba ho jakkoliv identifikovat na stejné dotazy odpovídá webový server
stejně, ať jde o jakéhokoliv klienta na druhé straně. Zato v případě e-mailové
aplikace jsou požadavky opačné. Za prvé je potřeba zajistit nemožnost přístupu
bez autorizace proto web při logovací proceduře požaduje vyplnění existujícího
uživatelského jména a korespondujícího hesla. A za druhé je nutné při
simultánním obsluhování více klientů všechny odlišit. K tomu se hodí
programování webů pomocí sessions.
Session se vytvoří při logování uživatele do aplikace klientovi se pošle
jedinečný identifikující řetězec a na jeho základě server umožní v rámci této
session uchovávat proměnné. V průběhu následující práce klienta s webovou
aplikací se klient serveru vždy prokazuje obdrženým řetězcem. Každému právě
zavolanému skriptu jsou k dispozici proměnné, které byly nastaveny ostatními
skripty předtím. Typický skript, který zajišťuje logování uživatele, porovná,
zda přihlašující údaje odpovídají hodnotám v databázi, a pokud ano, nastaví
jistou proměnnou na hodnotu značící úspěšné nalogování. Ostatní skripty vždy v
úvodu danou proměnnou na tuto hodnotu testují a pokračují, pouze pokud vyhovuje
(pokud ne, požadují zadat přihlašovací jméno a heslo). Nastavení zpět se
provede při odlogování uživatele, čímž se zajistí následná nefunkčnost
jednotlivých součástí aplikace. Druhá možnost zneplatnění session je takzvané
vypršení. Pokud doba mezi aktuálním a minulým požadavkem je větší než daný
timeout, session se automaticky odloguje a požadavek na přístup do chráněných
sekcí opět vrátí přihlašovací formulář. To může být také alternativně řešeno
pomocí cookies, kdy klient prostě po určité době identifikaci nepošle (server
ji pak ale musí posílat s každou odpovědí, aby se čas měřil vždy od posledního
dotazu).

Identifikované spojení
K udržení identifikovatelného spojení, tedy k opakovanému předávání zmiňovaného
identifikačního řetězce, se nabízejí především dva kanály: hodnoty proměnných
přibalené do URL nebo cookies. Snadnější je pochopitelně použití cookies, neboť
právě pro tyto účely byla do protokolu HTTP zavedena. Jednou (při inicializaci
session) je identifikátor v cookie poslán klientovi a pozdější prokazování
totožnosti probíhá vlastně automaticky, neboť, jak bylo už v úvodu řečeno,
prohlížeč cookie posílá všem stránkám spadajícím pod danou doménu. V minulosti
ale weboví programátoři řešili problém, co s prohlížeči, které cookies
nepodporují, popř. co s uživateli, kteří mají cookies vypnuté. V tomto případě
je jedinou alternativou připsání identifikačního řetězce do každého odkazu,
např. takto:
<a href=stranka.php?SessionID=1234567890>,
resp. do formuláře:
<INPUT Type=hidden Name=SessionID Value="abc1234567890">,
čímž byla tato hodnota opět pro všechny skripty dostupná.

Bezpečnost
A nyní se konečně dostáváme k problému bezpečnosti systémů a aplikací,
využívajících zmíněné techniky. Předně je nutno říci, že standardně je celá
komunikace nešifrovaná a všechny hodnoty stejně tak jako odpovědi serveru se
přenášejí v otevřené podobě čitelné každému mezi vámi a serverem. Dále je na
místě podotknout, že jakýkoliv symetrický kryptografický systém tento problém
sám o sobě neřeší, pokud nebudou předem bezpečnou cestou vyměněny šifrovací
klíče.
Trochu mimo celou problematiku stojí takzvané kryptograficky bezpečné kontrolní
součty neboli hashe, popřípadě výtahy zpráv. Zde se o jejich funkci zmíníme jen
stručně. Běžně používaný kontrolní součet je matematická funkce, která ze
vstupu o proměnné délce vypočítá konstantně dlouhý výstup (zpravidla v řádu
stovky bitů) tak, aby se jakákoli případná změna vstupu projevila na výstupu, a
to čím více, tím lépe. Pokud má být taková funkce tzv. kryptograficky bezpečná,
musí splňovat kritérium naprosté jednocestnosti. Nejenže nesmí být možné
dopočítat původní vstup (což je samozřejmě vždy vzhledem ke zkrácení nemožné
funkce není prostá), ale navíc nesmí být zpětně spočitatelný jakýkoliv vstup
byť odlišný od původního který by vracel stejnou hodnotu. Nejznámějšími
používanými algoritmy jsou MD5 (Message Digest) a SHA-1 (Secure Hash
Algorithm). Alespoň jeden z nich bývá často jako funkce implementován v
server-side skriptovacích jazycích.
První využití těchto funkcí v oblasti webové bezpečnosti spočívá v ukládání
hashí hesel do databáze místo původních znění hesel. Při ověřování na tom
nesejde (porovnávat se bude pouze hash obdrženého hesla) a při případné
kompromitaci systému jsou důsledky o něco menší. Takovouto hodnotu ale nelze
poslat e-mailem uživateli, který své heslo zapomněl, a situace se musí
programátorsky vyřešit jinak. Jedinou odpovídající alternativou by bylo použití
asymetrické kryptografie: při zakládání účtu či změně hesla by uživatel vložil
svůj veřejný klíč, systém by jím heslo zašifroval, uložil a při ztrátě poslal.
To je však zbytečně složité. Podstatně jednoduší je poslání jakéhosi
autorizačního kódu a odkazu na stránku, kde lze heslo změnit. Stará hodnota tak
není potřeba a bezpečnost závisí jen na ověření identity u e-mailového serveru.
Celý tento proces se dá navíc vyřešit známým trikem, který opět využívá
hashovacích funkcí. V e-mailu uvedeme v odkazu na stránku umožňující změnu
hesla jako jeden parametr e-mailovou adresu, jako druhý hash adresy a nějaké
další tajné hodnoty. Ta je známa pouze skriptům na straně serveru, které při
ověřování opět hash spočítají. Pokud se obě hodnoty rovnají, provádí změnu
hesla ten, kdo je vlastníkem e-mailu zapsaného v databázi registrovaných
uživatelů.
Bezpečnost takto popsaného systému závisí na utajení identifikačního řetězce.
Při jeho znalosti může druhá strana duplikovat jakýkoliv HTTP dotaz a provést
to, čemuž se říká ukradení session. O konkrétních metodách, které se zde dají
použít, a o možné obraně proti nim, bude řeč dále. Jediná obecná metoda, která
může takový útok ztížit, je kontrola neměnnosti IP adresy klienta. Tedy test,
zda se aktuální IP shoduje s IP při logování. Kontrolu IP adresy můžeme provést
stejným trikem, jaký jsme si vysvětlili při řešení problému ztráty hesla, opět
bez nutnosti operování s databází. Při nalogování uživatele mu v odpovědi
pošleme hash řetězce složeného z jeho IP adresy a tajné hodnoty. Stejnou
hodnotu pak počítáme při každém dotazu a výsledky porovnáváme. Případný útočník
svoji IP zná, ale jelikož nezná tajnou hodnotu, nemůže tento řetězec dopočítat.

Problémy prohlížečů
Jak již bylo zmíněno, s kompromitací vzájemně předávaných hodnot bezpečnost
celého systému padá. Ukažme si základní metody, které k nechtěnému odtajnění
vedou a příslušné obrany proti nim.
První je zde bezpečnost cookies na disku. Uchovávání tajných informací v nich
je rozhodně rizikové, neboť hrozí jejich přečtení jak cizí osobou, tak v
případě chyby prohlížeče jakýmkoliv cizím webovým serverem. Takovéto chyby
patří, mimochodem, k nejčastějším a nejhůře se proti nim brání. Klasická cesta
k ukradení session vede přes převzetí domény na straně klienta, což bývá někdy
trochu nepřesně označováno jako cross-frame scripting. Jde o to, aby pod
kontextem vaší domény nemohla cizí stránka vkládat svůj HTML obsah. Uvažme
případ, kdy na zobrazování článků máme skript clanek.php s parametrem ID, který
značí číslo článku, a systém je naprogramován tak, že při neúspěšném vyhledání
v databázi skript vypíše: "Článek XY neexistuje". Zde hrozí vložení HTML kódu
místo čísla na pozici hodnoty ID, který by se tak pod naší doménou u klienta
provedl. Například při zavolání url clanek.php?ID=<SCRIPT></SCRIPT> systém
odpoví "Nelze najít článek <SCRIPT></SCRIPT>". Takto vložený kód má přístup ke
všem cookies daného serveru, která může odeslat kamkoliv jinam. Jak již bylo
řečeno, toto je známý a tisíckrát popsaný způsob, proti němuž je obrana
jednoduchá: všechna menšítka, většítka, uvozovky a apostrofy, které přijdou v
hodnotách proměnných, nebo cookies od klienta, před zpracováním převést na HTML
entity "&lt;", "&gt;", "&quot;" a "&apos;" v tomto pořadí.
Pokud programátor k udržení session použije předávání hodnoty v URL, vystavuje
se nebezpečí přečtení hodnoty pomocí tzv. referreru. Referrer je část HTTP
dotazu, která předává serveru adresu předcházející stránky. Obrana proti tomuto
průniku je taktéž jednoduchá: odkazy v textu pozměníme a přesměrování provedeme
JavaScriptem přes třetí skript s URL v parametru.









Komentáře
K tomuto článku není připojena žádná diskuze, nebo byla zakázána.