Jak limitovat autentizační požadavky anonymů

petersveter

Jak limitovat autentizační požadavky anonymů
« kdy: 28. 01. 2024, 11:38:14 »
Zaujimalo by ma, co je dobry sposob na limitovanie autentifikacnych poziadaviek na api? Cize sa bavime o prihlasovani.

Problem tohto specifickeho dopytuje je, ze sa tyka anonymnych uzivatelov a nemozno ich teda filtrovat polda ID ani podla IP adresy kedze zdielane IP su bezne. Odtlacok zariadenia tiez nie je spolahlivy.

Prakticky mi ide o ochranu proti brute-force utokom kedy sa utocnik pokusa uhadnut heslo napriklad, tak ako sa to stalo pri znamom utoku na apple v kauze "fappening" par rokov dozadu.

Jedna moznost je pouzit nejaky casovy JWT token, kedy si klient najprv vypyta token a az nasledne ho odosle na server spolu s prihlasovacimi udajmi. Tam sa len overi, ci token moze byt pouzity (tzn "not_before"). Problem je ze utocnik si moze vypytat takyto casovy token a opakovane ho pouzit pre brute-force utok nasledne.

Ochrana by bola dat tokenu aj "expire at" limit lenze to znovu utocnikovi umoznuje v danom casovom useku kedy je token platny vykonavat utok.

A samozrejme toto cele aj paralelne.

Dalsia ochrana by bola ulozit id tokenu v cache na servery, aby sa dal pouzit len raz, cize JWT straca zmysel. Problem je ale ze kvoli absencii identifikacie si utocnik moze vypytat paralelne nekonecno tokenov a utocit bez problemov dalej a navyse je to zataz na zdroje na servery kedze musi tie tokeny drzat v cache.

Cize tokeny zalozene na case nemaju zmysel(jedine ze mi tu unika nejaky dalsi dizajn, co by bolo dost fajn). A kedze nie je mozne jednoznacne identifikovat klienta, nemozno pouzit ziadne cielenie.

Preto jedine co ma napada, je "proof of work". Takze s kazdym loginom uzivatel musi poslat aj vysledok nejakeho vypoctu, ktory musi trvat nejaky cas, podobne ako bcrypt. Uzivatel by si mohol pred autorizaciou vyptat nejaky "seed" a ten nasledne aj s vysledkom odosle spolu s loginom na kontrolu. Utocnik teda moze sice paralelne vykonavat utok, lenze kazdy dopyt bude casovo limitovany na jeho strane. Cize napriklad z miliona dopytov by bolo len tisic. Co vie dost pomoct.

Alternativa je Verifiable Delay Function ktore plnia rovnaky ucel.

Potrebujem nieco co je mozne lahko implementovat na server aj na klienta, cize nemalo by to byt limitovane jazykom/kniznicou a teda pristup ku api by mohol byt vykonany v js, java, c++, go, rust, net... ak je znamy algoritmus na vypocet vysledku.
« Poslední změna: 28. 01. 2024, 12:17:33 od Petr Krčmář »


RDa

  • *****
  • 2 710
    • Zobrazit profil
    • E-mail
Re:Ako limitovat autentifikacne requesty pre anonymov
« Odpověď #1 kdy: 28. 01. 2024, 12:06:27 »
Resil bych to podle IP adres a podsiti - jejich barvenim ( neznama, utocici, prihlasovana, mixed ), a na kazdou skupinu aplikoval jiny rate-limit. Ty utocici muzes i rovnou hodit na 24h do blacklistu, jakozto fail-to-ban pristup.

Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #2 kdy: 28. 01. 2024, 12:36:08 »
Musíte ty uživatele nějak identifikovat. Pokud nechcete IP adresou, tak třeba e-mailem nebo telefonním číslem, které si ověříte, a teprve pak jim vydáte JWT. Nebo třeba účtem na sociálních sítích – prostě jakkoli, kde už je někdo ověřil před vámi nebo co jim ztíží získání účtu.

Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #3 kdy: 02. 02. 2024, 14:58:21 »
Ne , nejde to vyřešit vydáváním tokenů atd. Nejde je ani identifikovat, když=protože to jsou anonymové.  Jde je pouze limitovat. Otázka je , podle čeho segmentovat do skupin, lebo limitovat globálně všetkých je nezmysel. Podle IP stačí, Případně s maskou/24...

petersveter

Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #4 kdy: 02. 02. 2024, 20:24:06 »
Ne , nejde to vyřešit vydáváním tokenů atd. Nejde je ani identifikovat, když=protože to jsou anonymové.  Jde je pouze limitovat. Otázka je , podle čeho segmentovat do skupin, lebo limitovat globálně všetkých je nezmysel. Podle IP stačí, Případně s maskou/24...

Aktualne to neriesim lebo to nie je akutne ale napadlo ma proste robit jednoduchu vec - kombinacia vyssie uvedeneho.
Uzivatel na webe klikne na tlacidlo odoslat(prihlasovacie udaje), na server sa skriptom odosle request ktory mu vrati token/uuid a cas ktory musi cakat. Ked cas vyprsi, odosle sa na server tento token s prihlasovacimi udajmi. Na serveri sa drzi tento token v cache. Token ma velmi kratku zivotnost, napriklad minutu, takze to nie je velka zataz na system a tymto sa da riadit napor. Cim viac tokenov je v cache, tym dlhsia bude pre kazdy novy token doba cakania takze uzivatelia budu akoby vo fronte. Pre uzivatela to bude znamenat len ze sa mu na webe toci chvilku loader ale inak nic nepozoruje. Utocnik zase moze utocit ale jedine co dosiahne je ze bude musiet cakat dlhsie a dlhsie a dlhsie nez bude moct skusit prihlasenie. Bude tam samozrejme limit cakania aby bezni uzivatelia moc netrpeli a to je cele.

Na webe to samozrejme pojde urobit tak ze login bude popup ktory moze vyvolat ten prvotny request take uzivatle ked odosle login tak vlastne akoby uz cakal ale ani o tom nijak nevedel.


Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #5 kdy: 02. 02. 2024, 20:59:04 »
řekl bych, že chceš CSRF.

Asi bys měl popsat důvod proč o něčem takovém přemýšlíš.

Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #6 kdy: 02. 02. 2024, 21:15:22 »
řekl bych, že chceš CSRF.
To nic neřeší. Tím akorát omezíte přístup k následující stránce pouze pro ty, kteří navštívili předchozí stránku. Jenže pak jste akorát posunul problém, protože potřebujete nějak limitovat přístup k předchozí stránce.

Asi bys měl popsat důvod proč o něčem takovém přemýšlíš.
+1

Aktualne to neriesim lebo to nie je akutne ale napadlo ma proste robit jednoduchu vec - kombinacia vyssie uvedeneho.
Uzivatel na webe klikne na tlacidlo odoslat(prihlasovacie udaje), na server sa skriptom odosle request ktory mu vrati token/uuid a cas ktory musi cakat. Ked cas vyprsi, odosle sa na server tento token s prihlasovacimi udajmi. Na serveri sa drzi tento token v cache. Token ma velmi kratku zivotnost, napriklad minutu, takze to nie je velka zataz na system a tymto sa da riadit napor. Cim viac tokenov je v cache, tym dlhsia bude pre kazdy novy token doba cakania takze uzivatelia budu akoby vo fronte. Pre uzivatela to bude znamenat len ze sa mu na webe toci chvilku loader ale inak nic nepozoruje. Utocnik zase moze utocit ale jedine co dosiahne je ze bude musiet cakat dlhsie a dlhsie a dlhsie nez bude moct skusit prihlasenie. Bude tam samozrejme limit cakania aby bezni uzivatelia moc netrpeli a to je cele.

Na webe to samozrejme pojde urobit tak ze login bude popup ktory moze vyvolat ten prvotny request take uzivatle ked odosle login tak vlastne akoby uz cakal ale ani o tom nijak nevedel.
Takže útočník si vygeneruje třeba tisíc požadavků do fronty každou sekundu, po limitu čekání se bude moci přihlašovat libovolně, protože bude mít každou vteřinu tisíc nových lístečků z fronty a jenom bude používat ty, kterým už uplynul limit. Poctivý uživatel bue čekat vždy ten nastavený limit, protože frontu bude plnit útočník. Takže útočníkovi jste v ničem nezabránil, jenom jste to znepříjemnil legitimnímu uživateli. To nevypadá na dobrý postup.

Navíc pokud byste ty vydané lístky opravdu držel v cache, jenom tím umožňujete útočníkovi zaplnit cache a legitimní uživatele tak odstavit úplně. Přitom to držení lístečků v cache je úplně zbytečné. Dělá se to tak, že lístečky podepisujete – a pak si je nikde nemusíte pamatovat, jenom ověříte, že lístek, který vám klient předkládá, je správně podepsaný – a pak víte, že můžete věřit jeho obsahu.

Jak jsem psal, bez nějaké identifikace uživatelů (byť třeba IP adresou – ale ani to není žádná výhra) to nepůjde. Protože pokud nebudete uživatele jakkoli identifikovat, může si jeden uživatel požádat třeba o miliardu přístupů, a vy nemáte šanci poznat, že je to pořád jeden a ten samý.

petersveter

Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #7 kdy: 03. 02. 2024, 11:56:39 »
Filip, nie je to uplne tak a JWT nemozno pouzit lebo tieto tokeny musia byt pouzitelne iba raz, takze drzat nieco v cache sa nevyhnem a JWT straca vyznam kedze ma sice "not before" a "valild until", lenze staci len vyckat na dobu kedy je platny a potom urobit utok, cize nema skratka v tomto kontexte ziaden prinos lebo pravidla su ze token musi mat platnost od, do a moze byt pouzity iba raz. A tento stejt(pouzitie len raz) musi teda drzat server a nie klient(co je pripad jwt).

Ale skusim to popisat v krokoch:
1. A odosle token request, ten sa mu vrati a je tam cakacia doba 0.5sec
2. A vyplni svoje udaje a odosle ich po uplynuti 0.5sec aj s tokenom - toto riesi skript na webstranke, uzivatel nic nepozoruje
3. A sa prihlasil

Iny pripad:
1. A odosle token request a dostane odpoved s 0.5sec
2. B odosle token request, ale vo fronte je A tak sa mu vrati cakanie 0.6sec
3. C odosle token request, vo fronte su A a B, tak sa mu vrat icakanie 0.7sec
...
1. A sa prihlasi
2. B sa prihlasi
3. D odosle token request, vo fronte je stale C, tak sa vrati cakanie 0.6sec


Pripad s utocnikom:
1. A spravi 10 000 token requestov a dostane tokeny s cakanim od 0.5sec po 5sec(max limit povedzme)
2. B si vyziada token a dostane cakanie 5sec(max)
3. A robi programove prihlasenie ale s kazdym requestom musi cakat dlhsiu dobu takze jeh pokusy o prihlasnei budu "throttlovane"

Ano, utocnik moze pockat 5 sekund a potom naraz urobit 10 000 pokusov o prihlasneie s platnymi tokenmi. Tuna by potom musela do toho este vstupit IP adresa aby sa serializovala fronta a teda cakacia doba by bola podla cakajucich z  IP adresy a nie globalne podla poctu vsetkych cakajucich.

Ak by utocnik pouzil viacero strojov na utok, tak kazdy taky stroj by bol nasledne takto "serializovany" a teda by nemohol aj tak utocit paralelne, inak povedane jeden utocnik moze utocit iba z jedneho stroju kde sa mu podla ip kontroluje kolko requestov moze robit a teda moze utok paralizovat iba viacero strojmi kde ale kazdy stroj stale moze skusat len serializovane.

petersveter

Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #8 kdy: 03. 02. 2024, 11:59:22 »
řekl bych, že chceš CSRF.

Asi bys měl popsat důvod proč o něčem takovém přemýšlíš.

Je to v mojom prvom prispevku, staci len citat
Citace
Prakticky mi ide o ochranu proti brute-force utokom kedy sa utocnik pokusa uhadnut heslo

CSRF to tak uplne nie je lebo tam chyba praca s casom ktory sa pouziva na kontrolu throttlovania.

Samozrejme cela tato diskusia je len jedna idea ako k tomu pristupit. Som otvoreny aj inym napadom. Ale specificky mi skratka ide o ochranu prihlasovania proti utoku hrubou silou.
« Poslední změna: 03. 02. 2024, 12:01:25 od petersveter »

RDa

  • *****
  • 2 710
    • Zobrazit profil
    • E-mail
Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #9 kdy: 03. 02. 2024, 12:05:10 »
Myslim ze to, co vlastne hledate je "captcha", jakozto dalsi faktor, ktery lze pouzit i pro prvotni/anonymni pozadavky.

Kdyz ji udelate hodne po svem, tak nejake brute-force toolkity tam nebudou mit rozpoznavani.

Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #10 kdy: 03. 02. 2024, 12:32:47 »
Filip, nie je to uplne tak a JWT nemozno pouzit lebo tieto tokeny musia byt pouzitelne iba raz, takze drzat nieco v cache sa nevyhnem a JWT straca vyznam kedze ma sice "not before" a "valild until", lenze staci len vyckat na dobu kedy je platny a potom urobit utok, cize nema skratka v tomto kontexte ziaden prinos lebo pravidla su ze token musi mat platnost od, do a moze byt pouzity iba raz. A tento stejt(pouzitie len raz) musi teda drzat server a nie klient(co je pripad jwt).
Nemá smysl vydávat tokeny použitelné jenom jednou, když si jich každý může nechat vytvořit, kolik chce.

3. A robi programove prihlasenie ale s kazdym requestom musi cakat dlhsiu dobu takze jeh pokusy o prihlasnei budu "throttlovane"
Ne, útočník na nic čekat nemusí. Útočník si nechá každou vteřinu vygenerovat třeba sto tokenů, počká pět vteřin (za tu dobu nastřádá 500 tokenů), a pak už si vždycky jen ze zásoby tokenů, které má vygenerované, vybere takový, který je zrovna platný. Každou vteřinu mu přibude dalších sto tokenů, takže má neustále z čeho vybírat.

Tuna by potom musela do toho este vstupit IP adresa aby sa serializovala fronta a teda cakacia doba by bola podla cakajucich z  IP adresy a nie globalne podla poctu vsetkych cakajucich.
Takže to omezení nakonec uděláte na IP adresu. A můžete celou tu šarádu s tokeny a prostě budete limitovat počet přihlášení z jedné IP adresy.

Ak by utocnik pouzil viacero strojov na utok, tak kazdy taky stroj by bol nasledne takto "serializovany" a teda by nemohol aj tak utocit paralelne, inak povedane jeden utocnik moze utocit iba z jedneho stroju kde sa mu podla ip kontroluje kolko requestov moze robit a teda moze utok paralizovat iba viacero strojmi kde ale kazdy stroj stale moze skusat len serializovane.
Ne, útočník může útočit paralelně z více strojů, protože vy nevíte, že je to pořád ten samý útočník.

Představte si to tak, že útočník začíná už s tím, že čekací doba je maximální, tedy 5 sekund. (Tohoto stavu není pro útočníka problém dosáhnout.) Když útočník získá každou vteřinu tři tokeny (označím je písmeny a v závorce bude, od kolikáté sekundy platí), bude jeho zásoba tokenů postupně vypadat takhle:

Kód: [Vybrat]
1. A(5), B(5), C(5)
2. A(5), B(5), C(5), D(6), E(6), F(6)
3. A(5), B(5), C(5), D(6), E(6), F(6), G(7), H(7), I(7)
4. A(5), B(5), C(5), D(6), E(6), F(6), G(7), H(7), I(7), J(8), K(8), L(8)
5. D(6), E(6), F(6), G(7), H(7), I(7), J(8), K(8), L(8), M(9), N(9), O(9)
6. G(7), H(7), I(7), J(8), K(8), L(8), M(9), N(9), O(9), P(10), Q(10), R(10)
7. J(8), K(8), L(8), M(9), N(9), O(9), P(10), Q(10), R(10), S(11), T(11), U(11)
TJ. v 5. vteřině už mohl použít tři tokeny A, B, C, v 6. D, E , F atd. Tj. každou vteřinu tři token získá a tři může použít. Když mu to nebude stačit, získá každou vteřinu třeba 10, 100, 1 000 nebo 1 000 000 tokenů – podle toho, jak tlustou bude mít linku, jak tlustou linku budete mít vy a kolik unese váš server.

No a tohle celé může útočník spustit paralelně z kolika IP adres chce.

Jediné, čeho vaším způsobem docílíte, je to, že začátek útoku posunete maximálně o 5 vteřin (o ten maximální čas, který tokenům nastavíte). Tak dlouho bude trvat, než útočník bude moci použít první token, který získal.

Nezapomínejte na to, že když útočník není nijak identifikovaný, nic mu nebrání získat v každém okamžiku tolik tokenů, kolik jich váš server dokáže vydat. A že i když útočník tokeny používá, nic mu nebrání vedle získávat další tokeny.

petersveter

Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #11 kdy: 03. 02. 2024, 12:42:57 »
Myslim ze teda bude vhodne limitovat pocet requestov podla IP aby sa vyselektovali len adresy ktore pretazuju system, a nasledne sledovat neuspesne pokusy o prihlasenie(kedze viem identifikovat ucet podla emailu alebo akykolvek iny identifikator sa pouziva na prihlasenie) cim viem docielit ze z jednej IP adresy neprebehne viac nez X requestov za jednotku casu(napriklad 1000/minuta) a taktiez ze sa na jeden ucet nepokusi neuspesne prihlasit viac nez N krat za jednotku casu. Tym padom mam osetrene to ze utok mi nelimituje realnych uzivatelov lebo request limiter bude podla ip a teda sa bude tykat iba utocnika alebo nejakej siete z ktorej pristupuje, a tiez ak by utocil na jeden ucet z rozynch adries tak to bude ostrene ze napriklad 3 zlyhane pokusy o prihlasenie na rovnaky ucet v ramci napriklad 5 minut zablokuju moznost sa prihlasit to tohto uctu na nejaku dobu takze utocnik vlastne moze utocit len 3x na jeden ucet a potom musi ist na iny.

Wasper

  • ***
  • 120
    • Zobrazit profil
    • E-mail
Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #12 kdy: 03. 02. 2024, 14:53:02 »
A co takhle implementovat PoW = nechat klienta spočítat něco, co mu chvíli zabere, ale ověření je okamžité?

Názorný příklad - pokus je session id generovaná serverem, tak můžete požadovat dopočítání X tak, aby substr(sha256(X+session_id),1,5) == "12345", při špatném loginu tu session samozřejmě zrušíte.

viz https://en.wikipedia.org/wiki/Proof_of_work

petersveter

Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #13 kdy: 03. 02. 2024, 16:56:54 »
A co takhle implementovat PoW = nechat klienta spočítat něco, co mu chvíli zabere, ale ověření je okamžité?

Názorný příklad - pokus je session id generovaná serverem, tak můžete požadovat dopočítání X tak, aby substr(sha256(X+session_id),1,5) == "12345", při špatném loginu tu session samozřejmě zrušíte.

viz https://en.wikipedia.org/wiki/Proof_of_work

Ano, Proof of Work alebo Verifiable Delay Function boli originalne to co som chcel riesit ale na koniec som od toho upustil a beriem to skor ako taku nudzovku - posledne riesenie. Vzhladom na to ze ten casovy token docieli totozny vysledok ale  jednoduchsie. Rozmyslal som aj nad niecim ako je reverzny bcrypt. Len mne ide primarne o cas a roznorodost hardveru vnasa privela variability do takehoto riesenia. I ked je pravda ze som to prilis hlboko neskumal(ani som nenasiel moc kniznic/zavedenych postpov popravde) a vecsinou to skoncilo niekde "nech klient pocita bitcoin".

Ono v konencom dosledku limitovat requesty je hracka, primarne mi slo o to zabranit utok hrubou silou ale ako som pisal, to sa da lahko poriesit limitom neuspesnych prihlaseni a je po probleme.

Re:Jak limitovat autentizační požadavky anonymů
« Odpověď #14 kdy: 03. 02. 2024, 19:56:23 »
Jak už tady někdo psal, je dobré popsat(nebo si rozmyslet) ten důvod . To pak rozhodne , jestli ta limitace neúspěšných přihlášení je akceptovatelné potenciální DOS (=omezení) pro legitimní usery