Jeden z naších klientů nám poslal žádost o ověření situace, kdy mu přes kontaktní formulář umístěný na jeho stránkách cizojazyčná (především rusky a anglicky píšící) individua odesílají nesmyslná data. Zkrátka klasický formulářový spam. A již na první pohled bylo jasné, že to není obyčejný hloupý robot. Po analýze chování „útočníků“ jsme došli k závěru, že se jedná o skutečné prohlížeče pravděpodobně ovládané nějakým bot-netem.
IP adresy uživatelů pocházely typicky z oblasti Ukrajiny, Ruska a přilehlých států. Jedna IP adresa neprováděla odeslání formuláře více než dvakrát, nejméně s jednodenním rozestupem. User-agent uživatelů vypadal dost reálně, zpravidla operační systém Windows a prohlížeč Chrome nebo Firefox. Před odesláním vždy následovalo načtení stránky s formulářem a poté okamžité odeslání. Od načtení stránky po odeslání dat neuběhlo více než jedna, maximálně dvě vteřiny.
CSRF ochranu formulářů máme v Netwings 7 zapnutou by-default. Tudíž útočník byl skutečně chytrý robot nebo prohlížeč, neboť CSRF tokeny vkládáme přes Javascript, takže Javascript útočník rozhodně ovládal. Tomu nasvědčuje i fakt, že před odesláním vždy nejprve přistoupil na URL stárnky, na které se formulář nachází, a až poté jej odesílal - neposílal tedy rovnou POST požadavky na URL akce formuláře (což by mu pochopitelně kvůli CSRF ochraně neprošlo).
Klientovi jsme navrhli dvě varianty ochrany - jednu v podobě captchy, kdy uživatel před odesláním musí potvrdit, že není robot. Druhou, z našeho pohledu méně otravnou a více uživatelsky přívětivou, jsme nakonec i implementovali. Jedná se o zabránění příliš brzkému odeslání formuláře. K Nette formuláři se nad vybraným formulářem automaticky připojí skryté hidden pole, které má v data atributu uveden časový limit, po kterém se má pole odstranit - to zařídí obslužný Javascript. Na toto pole je poté navěšeno klasické Nette validační pravidlo, které ověřuje, že hodnota tohoto pole je prázdná - validace se tak děje jak na straně klienta tak i na straně serveru. V případě brzkého odeslání je tak útočníkovi/uživateli zobrazena hláška, že zkrátka musí chvíli počkat. Jako výchozí hodnotu prodlevy před možností odeslání jsme zvolili 3 vteřiny - rozumný kompromis mezi časem, za který formulář odesílali boti, a minimálním časem, za který je formulář schopen vyplnit skutečný človek (např. i za pomoci různých "předvyplňovátek" ala FormFiller apod.).
Tato ochrana je samozřejmě relativně jednoduše prolomitelné - stačí si zkrátka počkat. Nicméně je velmi snadno nasaditelná a v tomto případě i efektivní - od nasazení neregistrujem jediné prolomení, ani stížnosti od skutečných uživatelů na nemožnost odeslat formulář s reálnými daty - reálného uživatele webu tedy nijak neobtěžuje.
Nutno také dodat, že krátce po nasazení tohoto řešení Google oznámil, že brzy vypustí do světa Invisible reCAPTCHu, která by náš problém také řešila, pravděpodobně také daleko sofistikovanějším způsobem.