Chyba URL encodingu často vypadá jako drobný problém se zobrazením. Jediný znak však může změnit gramatiku requestu. Ampersand vytvoří další parametr, lomítko nový segment, plus se změní na mezeru a druhé dekódování promění data v syntaxi. Nejhorší případy vznikají, když proxy, framework a aplikace interpretují stejný text odlišně.
Každá komponenta má vlastní pravidla
V path lomítko odděluje segmenty, v query ampersand a rovná se tvoří parametry. Fragment se serveru neposílá. Funkce, která stejně escapuje celý string, nedokáže odlišit strukturu od dat.
Bezpečná konstrukce používá raw values, URL builder, encoder segmentu a query API. Transformace proběhne právě jednou na konečné hranici.
Konkatenace selže na běžných datech
Hodnota „R&D“ bez encodingu vytvoří druhý parametr. Plus v telefonu, hash v názvu a české znaky odkryjí další chyby. Test s abc neobsahuje žádný problematický znak.
Knihovna navíc řeší prázdné hodnoty, pole a opakování. Smlouva má určit kanonický tvar, protože servery mohou validní alternativy interpretovat jinak.
Dvojité kódování mění hodnotu
Mezera %20 se po dalším encodingu stane %2520. Jedno dekódování vrátí text %20, druhé mezeru. To rozbíjí routing, cache a podpisy.
Interní hodnota má zůstat raw. Vlastník finální URL ji zakóduje jednou, namísto předávání částečně zpracovaných stringů.
Opakované dekódování není oprava
Pravidlo „dekóduj, dokud se něco mění“ umožní odložit aktivaci syntaxe. Firewall vidí po prvním kroku jednu cestu a router po druhém jinou.
Infrastruktura potřebuje jednotnou normalizační fázi. Nejednoznačný a vícenásobně zakódovaný vstup je bezpečnější odmítnout.
Plus neznamená všude mezeru
Ve form-urlencoded představuje plus tradičně mezeru. V jiné části URL je obyčejným znakem. Standardní Base64 nebo telefon v query se může změnit ještě před aplikačním kódem.
Query builder skutečný plus správně ochrání. Base64URL snižuje konflikt, ale nenahrazuje správné parsování.
Encoded slash se mezi vrstvami chová různě
%2F může být součást ID, ale webserver jej může odmítnout nebo rozbalit před routingem. Jeden segment se pak stane dvěma a dřívější security check posuzoval jinou cestu.
Veřejné identifikátory mají pokud možno používat path-safe abecedu. Jinak se musí celé prostředí otestovat na jednotné chování.
Duplicitní parametry potřebují politiku
Query role=user&role=admin může parser chápat jako první hodnotu, poslední nebo pole. Pokud gateway kontroluje první a backend používá poslední, vzniká bypass.
Opakování se povolí jen pro dokumentované seznamy. Ostatní duplicity mají všechny vrstvy odmítnout shodně.
Podepsané URL vyžadují přesnou kanonizaci
HMAC může zahrnovat metodu, cestu a query. Pořadí parametrů, zápis procent, prázdné hodnoty a mezery musí být stejné na obou stranách. Sémanticky ekvivalentní URL mohou mít jiné podpisy.
Specifikace potřebuje test vectors. Default různých knihoven není dostatečná smlouva.
Redirect potřebuje allowlist, nikoli jen encoding
Parametr next může být dokonale zakódovaný a vést na phishingovou doménu. Encoding chrání syntax, ne cíl. Služba přijímá relativní interní cesty nebo ověřuje parsovaný host.
Textový prefix nestačí proti userinfo, backslashům a vícenásobnému encodingu. Kontroluje se vyřešená a normalizovaná adresa.
Unicode se nejprve mění na bajty
Percent-encoding pracuje s bajty. Český znak se zapíše v UTF-8 a každý potřebný byte dostane procentovou podobu. Nesoulad charsetů vytvoří po dekódování poškozený text.
Hosty používají také IDNA. Bezpečnostní rozhodnutí vychází z normalizovaného výstupu knihovny, ne z vizuální podobnosti.
Log nemusí ukazovat původní request
Proxy někdy zapíše již normalizovanou URL a aplikace jen parsované parametry. Při incidentu chybí text skutečně odeslaný klientem. Dvojité decoding potom vypadá nevysvětlitelně.
Raw request target a validovanou formu lze bezpečně korelovat request ID. Citlivé query hodnoty se musí redigovat.
HTTP klient může adresu znovu upravit
Test stringu před odesláním nedokazuje, co odešlo po síti. Knihovna může znovu zakódovat procento, seřadit parametry nebo doplnit slash. Integration test má ověřit request přijatý serverem.
Také redirecty procházejí novým cyklem parsování a patří do testu.
Limity jsou součástí bezpečnosti
Extrémně dlouhý request target zatíží proxy, parser, cache i logy dříve, než aplikace posoudí význam. Vrstvy mají sladit maximální délku, počet parametrů a velikost hodnoty.
Překročení limitu má vrátit předvídatelnou chybu a nekopírovat celý útočný vstup do logu.
Odmítnutí bývá bezpečnější než oprava
Neplatný escape, null byte nebo zakázané vícenásobné kódování má skončit 400. Tiché odstranění znaku může z neplatné identity vytvořit jiný existující zdroj.
Interní log popíše komponentu a pravidlo, externí odpověď nemusí odhalovat infrastrukturu.
Stejně důležité je určit jedinou vrstvu, která kódování vlastní. Jestli hodnotu postupně upraví klient, API gateway a cílová služba, procenta se mohou znovu stát vstupními daty. Rozhraní proto musí jasně říci, zda přijímá syrovou hodnotu, nebo hotovou zakódovanou komponentu. Jednoduchá smlouva mezi vrstvami odstraní mnoho chyb, které se jinak projeví pouze u neobvyklých znaků.
Při opravě produkční chyby je užitečné uložit test s původní problematickou hodnotou. Regresní sada pak chrání nejen jednu funkci, ale celý průchod přes klienta, proxy, router a aplikační parser, kde se interpretace mohla změnit.
To platí i pro redirecty.
Test musí projít celou cestu
Sada obsahuje mezery, plus, ampersand, rovná se, hash, slash, Unicode, již zakódované procento a duplicity. Ověřuje builder, proxy, router i zvolenou business operaci.
Encoding je spolehlivý, když jej vlastní jedna vrstva a všechny další pracují se stejnou strukturou.