Zámek jen v prohlížeči žádný zámek není
Co hlídá jen prohlížeč, není pravidlo. Je to nápověda. Kdo chce, otevře konzoli, pošle požadavek jiným programem, nebo prostě přijde z jiného zařízení, kde nápověda chybí. Zní to jako poučka z učebnice. Přesto jsem na to narazil ve vlastní appce a hodinu to hledal.
Tipovací režim, který nic neodemkl
Moje Tipovačka na mistrovství světa má uzávěrku: po ní už se tipovat nedá. Pro výjimky, třeba když někdo nestihl vsadit, jsem do ní kdysi přidal „tipovací režim". Stačil parametr v adrese nebo příznak uložený v prohlížeči a formulář tipů se po uzávěrce znovu otevřel.
Pak mi kamarád napsal, že mu odkaz nefunguje. Mně fungoval. Vypadalo to na problém se sdílením odkazu. Ve skutečnosti za tím byly tři příčiny najednou:
- Mně to „šlo", protože jsem měl příznak v prohlížeči uložený z dřívějška.
- Kamarád měl appku nainstalovanou na ploše telefonu. Ta startuje vždycky na úvodní adrese bez parametrů, takže režim cestou zmizel.
- A hlavně: uzávěrku hlídá databáze na serveru a ta o žádném režimu neví. I kdyby se formulář otevřel, uložení tipu by server odmítl. Oběma.
Režim odemkl obrazovku, ne pravidlo. Oprava proto šla opačně: výjimku teď povoluje server. Uzávěrku posune požadavek chráněný PINem a appka se odemkne sama, protože čte tentýž údaj. Klient pravidlo jen zobrazuje.
Stejná past u každého formuláře
U webových formulářů je tahle chyba nejčastější. Povinná pole, formát e-mailu, maximální délku, to všechno jde hlídat v prohlížeči. A mělo by se, protože člověk dostane odpověď hned. Jenže formulář je jen jeden ze způsobů, jak poslat data na server. Robot ho nevyplňuje. Pošle požadavek rovnou a vaši kontrolu v JavaScriptu vůbec nespustí.
Neznamená to, že je kontrola v prohlížeči zbytečná. Je to služba člověku: dozví se o překlepu v e-mailu hned, ne až po odeslání, a nemusí vyplňovat všechno znovu. Jen jí nesmí nikdo svěřit bezpečnost. Kontrola v prohlížeči je pro lidi, kontrola na serveru pro všechny ostatní. Když chybí ta první, formulář je nepohodlný. Když chybí ta druhá, je děravý, a na první pohled to nepoznáte, protože pro běžného návštěvníka funguje úplně stejně.
Co tedy musí umět server, i když prohlížeč totéž hlídá taky:
- Validace. Znovu a celá: délka, formát, povinná pole, povolené hodnoty. Co nesedí, server odmítne, ať to přišlo odkudkoli.
- Žádné konce řádků v hlavičkách e-mailu. Když se jméno nebo e-mail z formuláře dostane do hlavičky zprávy a obsahuje konec řádku, útočník si přidá vlastní hlavičky, třeba další příjemce. Konce řádků musí pryč a e-mail musí projít kontrolou formátu.
- Escapování při výpisu. Text od návštěvníka je text, ne HTML. Kde se vypisuje, převede se tak, aby se
<script>ukázal jako písmena a nespustil se. - Token. Server při načtení stránky vydá jednorázový token a formulář ho musí vrátit. Požadavek bez platného tokenu server nepřijme.
- Limit. Jedna zpráva za minutu z jedné adresy. Člověk to nepozná, robot ano.
- Past na roboty. Pole, které člověk nevidí a robot ho vyplní. Server pak robotovi odpoví „díky", aby nezkoušel jiné cesty, a zprávu zahodí.
Jak to vypadá tady
Kontaktní formulář na tomhle webu dělá všechno z toho seznamu. Validaci má v prohlížeči kvůli pohodlí a na serveru kvůli bezpečnosti. Ta serverová má vlastní testy: diakritika, emoji, dlouhá zpráva, konec řádku ve jméně i HTML ve zprávě. Když si vypnete JavaScript, server zprávu nepřijme, protože bez skriptu formulář nemá kde vzít token. Dostanete ale srozumitelnou hlášku s e-mailem, kam napsat. Pohodlí může chybět, pravidlo ne.
Pravidlo
Klient smí zobrazovat, rozhoduje server. Každý „režim", „admin příznak" nebo „odemčeno" uložené v prohlížeči si kdokoli nastaví sám. Když se má povolit výjimka, povolí ji server a klient se podle něj zařídí.
Jestli vás zajímá, jak je na tom váš web, zkuste kontrolu webu. Formuláře zevnitř neotestuje, ale ukáže třeba, jestli web posílá bezpečnostní hlavičky, jede přes HTTPS a má formuláře chráněné proti robotům.