Chyba URL encodingu sa často prejaví iba pri mene s medzerou, externom identifikátore obsahujúcom lomku alebo podpísanom odkaze. Bežné ASCII príklady fungujú, preto sa problém dostane do produkcie. Príčinou nebýva samotné percent encoding pravidlo, ale nejasné vlastníctvo medzi klientom, HTTP knižnicou, proxy, frameworkom a aplikáciou. Každá vrstva môže hodnotu zakódovať alebo dekódovať ešte raz.
Každý komponent má inú povolenú syntax
Host, path segment, celý path, query name, query value a fragment nie sú zameniteľné. Lomka je dátom vo vnútri segmentu, ale oddeľovačom v celej ceste. Ampersand vo value musí byť chránený, inak otvorí ďalší parameter.
Jedna globálna escape funkcia bez informácie o kontexte nemôže rozhodnúť správne. Builder API má prijímať komponenty oddelene.
Konkatenácia zlyhá na úplne bežných dátach
Kód "?q=" + value funguje pre slovo, no hodnota A&B vytvorí ďalší parameter a x=y môže zmeniť interpretáciu. V ceste meno a/b vytvorí nový segment.
Najprv sa kóduje dynamická komponenta, potom sa pridajú štrukturálne znaky. Hotový výsledok je vhodné znovu parsovať a overiť očakávaný host, cestu a počet parametrov.
Dvojité kódovanie mení percento na dáta
Medzera zapísaná ako %20 sa po ďalšom encodingu zmení na %2520. Jedno dekódovanie potom vráti text %20, nie medzeru. K chybe dochádza, keď klient posiela hotovú encoded value a SDK predpokladá raw text.
Kontrakt musí jasne uviesť, ktorú podobu prijíma. „Zakóduj, ak ešte nie je zakódované“ nemožno spoľahlivo určiť podľa vzhľadu, pretože percentová sekvencia môže byť legitímnym textom.
Opakované decode nie je oprava
Niektoré aplikácie dekódujú dovtedy, kým sa string nemení. Tým môžu vytvoriť lomku, bodkový segment alebo markup až po bezpečnostnej kontrole. Router a autorizačná vrstva potom pracujú s inými identitami.
Každá hranica dekóduje presne raz podľa zmluvy. Neplatný escape alebo neočakávaná druhá vrstva sa odmietne, nie „opraví“.
Plus znamená medzeru iba v určitom formáte
Form-urlencoded parser tradične interpretuje plus ako medzeru. V path alebo všeobecnej URL syntaxi môže byť plus doslovný znak. Base64 hodnota vložená do query preto často príde poškodená.
Base64URL sa tejto kolízii vyhýba. Ak protokol vyžaduje štandardné Base64, value musí byť správne percent-encoded a nesmie prejsť ďalším ručným decode.
Encoded slash má medzi vrstvami rozdielny význam
%2F môže proxy odmietnuť, zachovať alebo zmeniť na lomku pred routingom. Backend potom vidí iný počet segmentov než edge bezpečnostná kontrola. Podobné rozdiely vznikajú pri encoded dot segments.
Citlivý identifikátor s ľubovoľnými bajtmi je bezpečnejšie preniesť v query, URL-safe abecede alebo request body než spoliehať na encoded slash v path.
Duplicitné parametre potrebujú jedno pravidlo
Pri ?role=user&role=admin môže WAF čítať prvú hodnotu a framework poslednú. Iný parser vytvorí pole. Útočník využije rozdiel medzi validáciou a business logikou.
API má pre každý parameter určiť, či sa môže opakovať. Nečakané duplicity sa odmietnu ešte pred autorizáciou a podpisovaním.
Podpísané URL vyžaduje presnú kanonizáciu
Podpis sa mení pri inom poradí parametrov, hex case, paddingu alebo reprezentácii medzery. Signer a verifier musia zostaviť rovnaký canonical string z rovnakých komponentov. Verifier nesmie slepo podpísať inú normalizovanú podobu než tú, ktorú neskôr použije router.
Špecifikácia má definovať sort, opakovanie, charset a zahrnuté komponenty. Testy potrebujú známe vektory aj nekanonické vstupy.
Open redirect nevyrieši escaping
Správne encoded hodnota next môže stále smerovať na útočníkov host. Syntax je validná, no navigačná politika nesprávna. Aplikácia má povoliť interné relatívne cesty alebo presný zoznam cieľov.
Po parsovaní treba kontrolovať výsledný host a schému, nie substring pôvodného textu. Backslash, user info a IDN môžu zmeniť to, čo človek považuje za doménu.
HTTP klient môže adresu zmeniť tesne pred odoslaním
String vypísaný v debug logu nemusí byť presne request target na sieti. Knižnica môže znovu zakódovať percento, zoradiť parametre, doplniť slash alebo nasledovať redirect. Test preto potrebuje server, ktorý zaznamená skutočne prijatú raw podobu.
Rovnako treba overiť redirect chain. Každý nový Location prejde ďalším cyklom parsovania a normalizácie, takže bezpečná prvá URL nemusí znamenať bezpečný konečný cieľ.
Odmietnutie je bezpečnejšie než tichá oprava
Neplatný percent escape, null byte alebo zakázaná viacnásobná reprezentácia má skončiť chybou. Odstránenie znaku môže z neplatnej identity vytvoriť iný existujúci zdroj. Klient potom nevie, čo server skutočne spracoval.
Interná diagnostika uvedie komponent a porušené pravidlo, externá odpoveď nemusí odhaľovať routing či filesystem. Oprava spätnej kompatibility má byť explicitná riadená migrácia s jasnou prevádzkovou metrikou a vlastníkom, nie skrytá vlastnosť parsera.
Unicode sa najprv mení na bajty
Percent encoding pracuje s bajtmi. Ak klient použije UTF-8 a server historický charset, rovnaké znaky sa dekódujú odlišne. Normalizované Unicode podoby môžu byť vizuálne rovnaké, ale byte-wise iné.
Kontrakt má používať UTF-8 a doménová normalizácia musí byť oddelená od URL decode. Inak podpis, lookup a zobrazenie nemusia pracovať s tou istou identitou.
Test musí prejsť celú cestu
Sada obsahuje medzeru, plus, ampersand, rovná sa, hash, lomku, percento, Unicode a duplicitné parametre. Overuje browser alebo HTTP klienta, CDN, proxy, router aj vybranú business operáciu. Samotný unit test encoderu nestačí.
Najspoľahlivejší encoding má jedného vlastníka a prísnu zmluvu. Keď všetky vrstvy pracujú s rovnakou štruktúrou, neobvyklý znak prestane byť produkčným prekvapením.