Ako prekonať mechanizmus CAPTCHA
Webové aplikácie často implementujú funkcionality ako prihlásenie pre užívateľov, rôzne vyhľadávacie funkcie, chatovacie funkcie a iné. Tieto funkcionality, ak nie sú dostatočne zabezpečené, sa stávajú terčom rôznych automatizovaných útokov – slovníkový útok na prihlasovací formulár, automatické vyhľadávanie za účelom prehľadávania obsahu, rôzne formy chatbotov a iné. Pre zabezpečenie funkcií pred automatizovanými skriptami sa často používa mechanizmus CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart). V tomto článku sa pozrieme na rôzne typy týchto mechanizmov a spôsoby ako ich obísť.
Ako už bol spomenuté v úvode, CAPTCHA slúži na zamedzenie automatického chovania. Mechanizmus funguje na princípe riešenia úlohy, ktorá je pre ľudí jednoduchá ale pre stroje/botov/klasické algoritmy výpočetne náročná. Často sa jedná napr. o obrázok obsahujúci text, ktorý je nejakým spôsobom poškodený a úlohou je tento text prepísať do textového poľa. Človek dokáže text prečítať aj v prípade, že je značne poškodený, zatiaľ čo rôzne OCR (Optical Character Recognition) algoritmy majú s takýmito úlohami problém.
Správne implementovaný CAPTCHA mechanizmus teda zabráni automatizovanému vykonávania určitých akcií. Ale v prípade, že CAPTCHA mechanizmus nie je implementovaný správne, sa môže vyskytnúť jeden alebo viacero spôsobov ako tento mechanizmus obísť a teda útočník znovu získa možnosť automatizovane vykonávať akcie. Typické útoky sú nasledovné.
Nezáleží na hodnote parametru
Tento problém nastáva, ak server nesprávne vyhodnocuje parameter s vyriešeným textom. CAPTCHA je teda vyriešená v prípade, že opísaný text je zlý alebo úplne chýba.
Replay útok
Spolu s riešením úlohy sa odosiela aj jej ID/zadanie. Útočník tak môže jednoducho vyriešiť jednu úlohu, zistiť aké parametre sa posielajú na server a následne posielať automatizované dotazy pričom riešenie úlohy (opísaný text) a zadanie úlohy (prípadne len jej ID) v týchto dotazoch zostáva rovnaké a menia sa len ostatné parametre. Tento typ útoku môže nastať aj v prípade, že sa ID úlohy neposiela priamo ale je zviazané so session ID užívateľa, pričom server toto ID nezneplatní pri úspešnom vyriešení.
Regenerate Session ID útok
K tomuto útoku môže dôjsť ak sú splnené tri podmienky:
- CAPTCHA úloha je zobrazená až po niekoľkých pokusoch
- ID riešenej úlohy je zviazané spolu so session ID
- Útočník je schopný získať nové session ID
Príklad útoku môže byť prihlasovací formulár, ktorý zobrazí CAPTCHA úlohu až po (napr.) 3 neúspešných pokusoch. Pretože útočník ešte nie je autentizovaný, môže jednoducho zažiadať o nové session ID a tým si resetovať počet neúspešných pokusov, čo vedie na možnosť slovníkového útoku bez nutnosti riešiť čo i len jednu CAPTCHA úlohu.
Variantou k tomuto útoku je, ak server identifikuje užívateľa na základe akejkoľvek užívateľom upraviteľnej hodnoty – to môžu byť rôzne HTTP hlavičky a pod. Útočníkovi potom stačí upraviť túto konkrétnu hodnotu, čím sa pre server stáva “neznámym“ a znovu môže vykonať určitý počet akcií bez riešenia CAPTCHA úlohy.
Toto bol popis najbežnejšie sa vyskytujúcich chýb a možnosti ich zneužitia. Ďalej si popíšeme útoky, ktoré úlohy neobchádzajú ale priamo ich riešia.
Riešenie CAPTCHA úloh
Ako prvé by bolo vhodné uviesť, že autor článku nie je v žiadnom prípade odborník na spracovanie obrazu či strojové učenie. Popísané metódy by nemali byť brané ako návod na prelomenie ale skôr ako ukážka, že aj človek, ktorý nemá veľké znalosti v danej problematike je schopný tieto a podobné metódy použiť, prípadne vytvoriť lepšie a účinnejšie metódy.
Vyššie popísané útoky nie sú jedinými útokmi proti CAPTCHA mechanizmu, no sú tými najčastejšími. Mimo tieto útoky sa ale dá na tento mechanizmus útočiť aj priamo, vytvorením algoritmu, ktorý danú úlohu vyrieši. Toto je možné buď v prípade, že daná úloha nie je až tak zložitá pre stroj – napr. znaky nie sú čitateľné priamo, no jednoduchým predspracovaním obrázku je možné následne použiť verejne dostupné OCR algoritmy. Ďalšou možnosťou je využitie tzv. strojového učenia. Jedná sa o algoritmy, ktoré po spracovaní veľkého množstva vyriešených úloh sa “naučia“ riešiť tento typ úloh.
Manuálne predspracovanie
Najskôr si popíšeme riešenie CAPTCHA úloh, ktoré na prvý pohľad môžu vyzerať bezpečne, no pomocou jednoduchého predspracovania, sme schopný tieto úlohy vyriešiť. Budeme sa zameriavať výhradne na CAPTCHA úlohy, ktoré majú za cieľ opísať text z obrázka. Náš hlavný cieľ v tomto type útoku je čo najviac pomôcť OCR nástroju, čo pre nás znamená, že v najideálnejšom prípade chceme pôvodný obrázok rozrezať na jednotlivé znaky a odstrániť čo najviac šumu/poškodenia.
Na nasledujúcich obrázkoch sú zobrazené rôzne typy CAPTCHA úloh. Na prvý pohlaď sa môže zdať, že minimálne niektoré z nich sú bezpečné a naozaj, pri spustení OCR nástroja na tieto obrázky, nedostaneme žiadny použiteľný výsledok.
Toto ale ešte neznamená, že cieľavedomý útočník nedokáže jednoduchým spôsobom upraviť dané obrázky tak, aby ich OCR nástroje prečítali. Už len pri prvom pohľade na tieto obrázky vieme povedať, že obsahujú niekoľko slabých miest:
- Šum v obrázku (pozadie, artefakty a všetko ostatné mimo znakov) je vykreslené iným odtieňom farby (prípadne úplne inou farbou) než sú jednotlivé znaky – je možné jednoducho odlíšiť čo je znak a čo nie
- Nedostatočná separácia jednotlivých znakov – je možné jednoducho určiť hranice jednotlivých znakov
- Ďalšími problémami môže byť malá znaková sada (použité iba čísla apod.), rovnaký font pre všetky znaky, rovnaká veľkosť znakov, natočenie znakov a pod.
Ako Proof-of-Concept si vyberieme jeden z vyššie uvedených obrázkov a navrhneme kroky, pomocou ktorých obrázok upravíme tak aby bol čitateľný pomocou OCR.
Keďže obrázok neobsahuje žiadne iné farby okrem odtieňov sivej, bude sa nám s ním jednoduchšie pracovať ako s čiernobielym obrázkom, kde každý pixel má hodnotu od 0 (čierna) po 255 (biela). Ďalším krokom zväčša býva prahovanie (thresholding). Ide o jednoduchú úpravu obrázka, pri ktorej konvertujeme hodnoty pixelov z pôvodného rozsahu 0 až 255 na hodnotu 0 alebo 255 podľa nami zvoleného prahu. Tento prah volíme experimentálne tak, aby sme zachovali čo najviac informácií o znakoch a naopak odstránili čo najviac šumu. Výsledok po tomto kroku môže vyzerať nasledovne.
Pri pohľade na výsledok si môžeme všimnúť rôzne malé artefakty (bodky, krátke čiary apod.). Odstránenie týchto artefaktov je jednoduché, stačí v obrázku nájsť všetky "spojité objekty" (množina pixelov ktoré sa dotýkajú aspoň jednou stranou) a spočítať ich veľkosť (počet pixelov, ktoré tvoria daný objekt). Následne odstránime objekty, ktoré sú tvorené malým počtom pixelov – predpokladáme, že znaky, ktoré nás zaujímajú sú veľké a teda tvorené veľkým počtom pixelov. Výsledok kroku je zobrazený na nasledujúcom obrázku.
Ďalej je nutné odstrániť artefakty, ktoré sú pozostatky tenkých čiar určených na zašumenie znakov. Prvým odlišujúcim znakom je, že tieto artefakty pozostávajú z tenkých čiar, pričom znaky sú vykreslené hrubším písmom. Odstránenie takých tenkých čiar tiež nie je zložité, no môže občas poškodiť vykreslené znaky. Algoritmus jednoducho hľadá čierne pixely, ktorých protiľahlé pixely (horizontálne alebo vertikálne) sú biele – tieto pixely následne odstráni (ich hodnotu nastaví na bielu).
V niektorých prípadoch dôjde k poškodeniu znakov. Toto môžeme vidieť vyššie na znaku C. V takomto prípade môžeme vykonať opravu pixelu – biely pixel nastavíme na čierny ak susedí s dostatočným množstvom čiernych pixelov.
Keďže nám predošlé kroky vytvorili znovu ďalšie artefakty tvorené malými objektami, odstránime ich rovnako ako v predošlom kroku. Finálna verzia obrázku pred orezaním vyzerá nasledujúco.
Priamo nad týmto obrázkom je možné spustiť OCR nástroj, no z našich experimentov sa osvedčilo orezať obrázok na jednotlivé znaky.
Takto orezané znaky už jednoducho detekuje OCR nástroj ako napr. gocr. Kroky v tejto metóde nie sú nijako sofistikované a ide o veľmi primitívne predspracovanie, ktoré ale aj tak za určitých okolností vedie k jednoduchému vyriešeniu aj zložitejšej CAPTCHA úlohy.
V prípade tohoto CAPCHA mechanizmu bola ale fatálna špecifická chyba. Algoritmus pri generovaní úlohy získal ID zo session ID (ID určuje znaky ktoré budú vykreslené) ale šum generoval náhodne na základe času v momente generovania. Kvôli tejto chybe bolo možné vygenerovať rôzne úlohy, ktoré zdieľali rovnaké riešenie ale boli poškodené rôznym spôsobom.
Táto chyba umožnila riešiť jednu úlohu pri rôznom poškodený a tým získať presnejší výsledok. Úspešnosť algoritmu pri riešení je nakoniec 99%.
Prečo robiť veci manuálne, keď nato môžeme pustiť terminátora?
Za posledné roky umelá inteligencia prešla rapídnym vývojom a to sa prejavilo aj v problematike spracovania obrazu. Vďaka rôznym knižniciam implementujúcim algoritmy strojového učenia si dnes môže tieto algoritmy bez akejkoľvek námahy vyskúšať každý. Pozrime sa na príklad CAPTCHA úloh, ktoré sú prítomne vo frameworku Liferay.
Liferay ponúka veľký počet rôznych typov úloh s rôznou zložitosťou. Pri generovaní úlohy sa náhodne vyberie jeden z typov a ten sa zobrazí užívateľovi.
Na zdolanie takto náročnej úlohy použijeme algoritmy strojového učenia a to konkrétne CNN (Convolutional Neural Network). Algoritmy strojového učenia pracujú v dvoch fázach. V prvej fázy sa algoritmus učí na príkladoch, ktoré mu ukážete. V jednoduchosti sa dá povedať, že algoritmu ukážete znak A, on vám odpovie aký znak si myslí, že vidí a na základe jeho odpovede sa upravia jeho interné parametre. Tento proces sa robí automaticky a opakuje sa kým algoritmus nie je schopný rozpoznať všetky požadované znaky s požadovanou presnosťou. Toto je samozrejme veľmi zjednodušený popis a v skutočnosti je to o niečo zložitejšie, no stačí nám na obecné pochopenie pre potreby tohoto článku. Prvá fáza je teda fáza učenia a po dokončení je algoritmus pripravený na druhú fázu. V tejto fázy používame algoritmus na rozpoznanie konkrétnych znakov z CAPTCHA úloh, pričom už algoritmus neučíme – výsledok, ktorý nám dá je finálny, teda použijeme ho ako odpoveď aplikácii na konkrétnu CAPTCHA úlohu.
Na to aby sme mohli použiť takýto algoritmus, potrebujeme veľké množstvo vyriešených úloh – na týchto úlohách sa náš algoritmus bude učiť. Túto tzn. trénovaciu sadu si vygenerujeme sami, úpravou Liferay frameworku, pričom vygenerujeme rádovo 100-a tisíce obrázkov. Obrázky rozdelíme do kategórii podľa typu danej úlohy – dokopy máme 32 kategórii. Pre každú kategóriu budeme trénovať zvlášť jednu CNN a nakoniec natrénujeme jednu špeciálnu CNN, ktorá bude rozhodovať o akú kategóriu ide. Celý proces riešenia bude teda nasledujúci.
Úspešnosť nášho riešenia bola okolo 70%. Táto úspešnosť by išla určite zvýšiť lepším nastavením a dizajnom samotnej CNN. Na druhej strane, je treba zobrať do úvahy, že Liferay občas vygeneruje CAPTCHA obrázky podobné nasledujúcim. Takéto obrázky nie je schopný vyriešiť ani človek a teda 70% je nakoniec pekný výsledok.
Ako získať vyriešené CAPTCHA
Aby sme mohli použiť strojové učenie je treba získať veľké množstvo vyriešených úloh. V prípade Liferay portálu si ich môžeme jednoducho vygenerovať ale v iných prípadoch to nemusí byť tak jednoduché.
Našťastie na tento problém existuje riešenie.
Na internete existuje množstvo služieb poskytujúcich riešenie CAPCHA mechanizmov. Tieto služby fungujú vďaka obetavým ľudom, ktorý CAPTCHA úlohy vyriešia za vás za malý poplatok. Úlohy im môžete posielať buď v reálnom čase alebo v prípade učenia umelej inteligencie môžete nechať vyriešiť celú sadu úloh naraz. Jednou z takýchto služieb je 2Cpatcha:
Pomocou služieb ako je 2Captcha a iné už nie je problém získať kľudne aj rádovo desaťtisíce vyriešených úloh.
Záver
Ukázali sme, že na zamedzenie automatizovaných nástrojov často nestačí len implementovať naivný CAPTCHA mechanizmus ale, že tento mechanizmus musí byť správne implementovaný a tiež musí mať určitú úroveň zložitosti. Vzhľadom na rýchlo rozvíjajúcu sa oblasť umelej inteligencie je nutné s týmto vývojom udržať krok a vyvíjať nové spôsoby, ktorými je možné rozlíšiť ľudí a strojové aktivity.