DB desgin+funkcionalita proti brute-force

DB desgin+funkcionalita proti brute-force
« kdy: 07. 09. 2019, 10:51:39 »
Dobrý den,

chtěl bych Vás moc poprosit o radu ohledně designu databáze proti brute-force útokům.

Moje momentální idea:
Tabulka v databázi login_attempt(id, ip_address, username, timestamp, succcess), kam se logují všechny pokusy o příhlášení (úspěšné/neúspěšné).
Při každém loginu se zkontroluje, kolikrát uživatel za posledních 5mint se pokoušel přihlásit a pokud to překročí nějakou danou hranici (což je třeba 8 řekněme), tak by se mu měl dát ban.
Ted je otázka, jak navrhnout tu druhou tabulku.
Pokud bych ji pojmenoval ban (id, ip_address, timestamp start, timestamp end) a zkontroloval bych, jestli to uživatelské jméno existuje a jištak bych dal neaktivní účet na 1 den. Ale v té tabulce není vůbec zahrnuto username, což by bylo asi dobré tam zahrnout.
Další věc je, jestli ta tabulka ban by měla mít nějaký vztah (vazbu 1:N) s tabulkou user. Tady problém je, že ten username může být jméno, které v databázi (v user) neexistuje, takže to asi není úplně správný ne?

Jakým způsobem by to mělo být tohle správně navrhnuto?

Děkuji za pomoc


RDa

  • *****
  • 2 465
    • Zobrazit profil
    • E-mail
Re:DB desgin+funkcionalita proti brute-force
« Odpověď #1 kdy: 07. 09. 2019, 11:13:13 »
A proc chces banovat uzivatele, kdyz se mu nekdo snazi neuspesne prihlasit do uctu?

Obrana proti bruteforce by mohla byt treba zalozena na poctu neuspechu z IP adresy (resp. jeji casti, napr. site typu C) a pak banovat tenhle zdroj na dva dny, prihlasovani by nejprve kontrolovalo zda neni IP v tomto blacklistu.

Re:DB desgin+funkcionalita proti brute-force
« Odpověď #2 kdy: 07. 09. 2019, 11:16:28 »
A proc chces banovat uzivatele, kdyz se mu nekdo snazi neuspesne prihlasit do uctu?

Obrana proti bruteforce by mohla byt treba zalozena na poctu neuspechu z IP adresy (resp. jeji casti, napr. site typu C) a pak banovat tenhle zdroj na dva dny, prihlasovani by nejprve kontrolovalo zda neni IP v tomto blacklistu.

Takže mám udělat jenom tabulku:
ban (id, ip_adresa, timestamp odkdy, timestamp do kdy)? Bez jakýkoli vazeb? A sem budu dávat bloklé IP adresy, od kterých bylo nějaké podezřelé chování?

gill

  • ****
  • 270
    • Zobrazit profil
    • E-mail
Re:DB desgin+funkcionalita proti brute-force
« Odpověď #3 kdy: 07. 09. 2019, 11:16:59 »
používáte nějaký framework? Na tohle existují hotová řešení. V djangu třeba axes.

Re:DB desgin+funkcionalita proti brute-force
« Odpověď #4 kdy: 07. 09. 2019, 11:22:53 »
používáte nějaký framework? Na tohle existují hotová řešení. V djangu třeba axes.

spring boot. Nejsem si úplně vědom, že by tady něco takového bylo...


gill

  • ****
  • 270
    • Zobrazit profil
    • E-mail
Re:DB desgin+funkcionalita proti brute-force
« Odpověď #5 kdy: 07. 09. 2019, 11:40:36 »
používáte nějaký framework? Na tohle existují hotová řešení. V djangu třeba axes.

spring boot. Nejsem si úplně vědom, že by tady něco takového bylo...

s tím nemám zkušenost, ale zkusil bych googlit. Určitě stejný problém řešili i jiní. U funkcionalit týkajících se bezpečnosti je lepší používat ozkoušená řešení, když to budete psát sám, zbytečně riskujete chybu. Zbytečně budete plýtvat budgetem na funkcionalitu nesouvisející s vaší aplikací.

Re:DB desgin+funkcionalita proti brute-force
« Odpověď #6 kdy: 07. 09. 2019, 11:47:22 »
Pokud budete při útoku hrubou silou na hesla zapisovat každý pokus do databáze, je to ideální příležitost pro DoS – tedy aby útočník vytížil vaši databázi neúspěšnými pokusy o přihlášení natolik, že už nezvládne nic jiného.

Blokovat uživatele při opakovaném zadání chybného hesla (bez dalších podmínek) je zase pro útočníka ideální způsob, jak zablokovat přístup konkrétnímu uživateli (tedy DoS ne na celý server, ale na vybrané uživatele). Stačí každé dvě minuty minut učinit neúspěšný pokus o přihlášení daným uživatelským jménem, a ten uživatel už se nikdy nepřihlásí.

Omezovat to na konkrétní IP adresu není řešení – v době všudypřítomných NATů může mít útočník docela snadno stejnou IP adresu, jako oběť. A naopak pokud by se někdo pokoušel hádat hesla, může dělat každý pokus z jiné IP adresy.

Z toho plyne, že neúspěšné pokusy o přihlášení bych držel jenom v paměti a s minimem informací, ať je to pro server co nejméně náročné. V případě překročení počtu neúspěšných pokusů by nemělo dojít k blokaci účtu, ale jenom ke zpomalení hádání, ale umožnit uživateli dál projít – tj. použít tam nějakou CAPTCHA. Spíš složitější, aby se nedala hádat automaticky, oprávněnému uživateli to holt v případě útoku na jeho účet dá víc práce přihlásit se, ale pořád bude mít tu možnost. Do třetice by tam měla být kontrola, aby uživatel nemohl zadat vyloženě slabé heslo.

Pokud uživateli chcete dát možnost zabezpečit svůj účet víc, dejte mu možnost spárovat účet s jinými službami, přes které se může přihlásit – Google, Facebook, Twitter, MojeID, obecné OpenID. Když to uživatel použije, zbavíte se v jeho případě zodpovědnosti za bezpečné přihlašování :-) Dále umožněte uživateli zapnout si dvoufaktorovou autentizaci, tj. přihlašování pomocí jednorázových hesel.

Re:DB desgin+funkcionalita proti brute-force
« Odpověď #7 kdy: 07. 09. 2019, 12:37:34 »
Pokud budete při útoku hrubou silou na hesla zapisovat každý pokus do databáze, je to ideální příležitost pro DoS – tedy aby útočník vytížil vaši databázi neúspěšnými pokusy o přihlášení natolik, že už nezvládne nic jiného.

Blokovat uživatele při opakovaném zadání chybného hesla (bez dalších podmínek) je zase pro útočníka ideální způsob, jak zablokovat přístup konkrétnímu uživateli (tedy DoS ne na celý server, ale na vybrané uživatele). Stačí každé dvě minuty minut učinit neúspěšný pokus o přihlášení daným uživatelským jménem, a ten uživatel už se nikdy nepřihlásí.

Omezovat to na konkrétní IP adresu není řešení – v době všudypřítomných NATů může mít útočník docela snadno stejnou IP adresu, jako oběť. A naopak pokud by se někdo pokoušel hádat hesla, může dělat každý pokus z jiné IP adresy.

Z toho plyne, že neúspěšné pokusy o přihlášení bych držel jenom v paměti a s minimem informací, ať je to pro server co nejméně náročné. V případě překročení počtu neúspěšných pokusů by nemělo dojít k blokaci účtu, ale jenom ke zpomalení hádání, ale umožnit uživateli dál projít – tj. použít tam nějakou CAPTCHA. Spíš složitější, aby se nedala hádat automaticky, oprávněnému uživateli to holt v případě útoku na jeho účet dá víc práce přihlásit se, ale pořád bude mít tu možnost. Do třetice by tam měla být kontrola, aby uživatel nemohl zadat vyloženě slabé heslo.

Pokud uživateli chcete dát možnost zabezpečit svůj účet víc, dejte mu možnost spárovat účet s jinými službami, přes které se může přihlásit – Google, Facebook, Twitter, MojeID, obecné OpenID. Když to uživatel použije, zbavíte se v jeho případě zodpovědnosti za bezpečné přihlašování :-) Dále umožněte uživateli zapnout si dvoufaktorovou autentizaci, tj. přihlašování pomocí jednorázových hesel.

Takže když použiji tento tutorial, který používá cache místo DB, tak je to lepší řešení? + bych přidal k tomu ještě tu captchu
https://www.baeldung.com/spring-security-block-brute-force-authentication-attempts

Re:DB desgin+funkcionalita proti brute-force
« Odpověď #8 kdy: 07. 09. 2019, 13:08:42 »
Takže když použiji tento tutorial, který používá cache místo DB, tak je to lepší řešení? + bych přidal k tomu ještě tu captchu
https://www.baeldung.com/spring-security-block-brute-force-authentication-attempts
Určitě je to lepší, než zapisovat každý neúspěšný pokus o přihlášení do relační databáze. Vázat to na IP adresu odradí primitivní pokusy, pro odhodlaného útočníka nebude problém zkoušet to z různých IP adres. Taky ten tutorial moc nepočítá s IPv6 – tam koncový uživatel dostane celou síť, takže nemá smysl rozlišovat jednotlivé IPv6 adresy, ale je potřeba brát celou /64 síť jako jednoho uživatele. A určitě bych neblokoval toho uživatele natvrdo, jak je to v tom tutoriálu, ale použil bych nějakou CAPTCHA, jak jsem psal.

Také je potřeba zacházet pečlivěji s hlavičkou X-Forwarded-For – pokud aplikace nebude schovaná za reverzním proxy serverem, musí tuhle hlavičku ignorovat, protože by ji mohl klidně nastavit útočník. Naopak pokud bude za reverzním proxy serverem, musí ten server zajistit vymazání případné hlavičky od útočníka a vložení nové hlavičky se správnou hodnotou. A aplikace pak musí používat hodnotu z téhle hlavičky.

Re:DB desgin+funkcionalita proti brute-force
« Odpověď #9 kdy: 07. 09. 2019, 13:22:43 »
Takže když použiji tento tutorial, který používá cache místo DB, tak je to lepší řešení? + bych přidal k tomu ještě tu captchu
https://www.baeldung.com/spring-security-block-brute-force-authentication-attempts
Určitě je to lepší, než zapisovat každý neúspěšný pokus o přihlášení do relační databáze. Vázat to na IP adresu odradí primitivní pokusy, pro odhodlaného útočníka nebude problém zkoušet to z různých IP adres. Taky ten tutorial moc nepočítá s IPv6 – tam koncový uživatel dostane celou síť, takže nemá smysl rozlišovat jednotlivé IPv6 adresy, ale je potřeba brát celou /64 síť jako jednoho uživatele. A určitě bych neblokoval toho uživatele natvrdo, jak je to v tom tutoriálu, ale použil bych nějakou CAPTCHA, jak jsem psal.

Také je potřeba zacházet pečlivěji s hlavičkou X-Forwarded-For – pokud aplikace nebude schovaná za reverzním proxy serverem, musí tuhle hlavičku ignorovat, protože by ji mohl klidně nastavit útočník. Naopak pokud bude za reverzním proxy serverem, musí ten server zajistit vymazání případné hlavičky od útočníka a vložení nové hlavičky se správnou hodnotou. A aplikace pak musí používat hodnotu z téhle hlavičky.


A jak mám reagoval na IPv6 adresu?

Čili pokud IP adresu zjistím tímto způsobem a aplikace neni schovaná za reverzním proxy, tak ji mám ignorovat a vracet vždy request.getRemoteAddr();?
Kód: [Vybrat]
private String getClientIP() {
        String xfHeader = request.getHeader("X-Forwarded-For");
        if (xfHeader == null){
            return request.getRemoteAddr();
        }
        return xfHeader.split(",")[0];
    }
}

Re:DB desgin+funkcionalita proti brute-force
« Odpověď #10 kdy: 07. 09. 2019, 14:36:40 »
Pokud aplikace není za reverzním proxy serverem, použijte jenom request.getRemoteAddr() a tu hlavičku ignorujte.

Podle mne není standardizováno, v jakém formátu má request.getRemoteAddr() IPv6 adresu vracet. Takže asi nezbyde, než ji parsovat a ořezávat na adresu sítě ručně. Nenašel jsem pro to ani žádnou utilitu ve Springu. Existuje knihovna pouze pro práci s IP adresami IPAddress – pomocí new IPAddressString("…"), pak ji buď můžete správně oříznout na adresu sítě a převézt zpět na String, nebo ji můžete přes    toFullString() rovnou převést na úplnou reprezentaci IPv6 adresy a pak prostě humpolácky použít 19 znaků zleva.