NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 21 - Bezpečnostní hrozby - Jak správně ukládat hesla?

V minulé lekci, Blog ve Spring Boot - Validace registračního formuláře, jsme přidali DTO pro registrační formulář a implementovali jsme jeho validaci.

V našem kurzu se dostáváme k ukládání uživatelských hesel, což je potenciální bezpečnostní hrozba. V dnešní době GDPR zákonů a vysokého bezpečnostního standardu, se chceme ve vlastním zájmu vyhnout bezpečnostním chybám v našich aplikacích. Záleží nám na tom, abyste byli opravdu dobří. Proto naše kurzy obsahují také vybraná témata z kurzů Dobrých praktik a Kyberbezpečnosti. Jak tedy hesla bezpečně uložit?

Bezpečnost – ukládání hesel - Databáze a Hibernate ve Spring Boot - Blog

Hesla se do databáze neukládají

Pro ukládání hesel nejen do databáze platí jedno jednoduché pravidlo:

Žádná hesla do databáze nikdy neukládáme!

K databázi se mohou dostat nepovolané osoby, např. při hackerském útoku na webhosting nebo naši aplikaci. Musíme si uvědomit, že hesla, zejména pokud jsou přiřazena k emailovým adresám, jsou velmi citlivá data. Velké procento uživatelů totiž používá to stejné heslo i ke své emailové schránce a na další služby. Útočník by tedy dostal tisíce vstupenek do emailových schránek našich uživatelů. Přes email není prakticky už žádný problém dostat se kamkoli jinam, stačí si na kteroukoli službu, např. Facebook, nechat poslat nové heslo do emailové schránky, kterou útočník ovládá. I kdyby u uživatelů email uložený nebyl, lze uživatele obvykle jednoduše spojit podle jména nebo jeho příspěvků s nějakým jiným účtem na internetu, získat jeho emailovou adresu, následně přístup do jeho schránky a tak i k dalším jím využívaným službám. Toto je mimo jiné důvod, proč emailové schránky obvykle chtějí dvoufázové ověření, nicméně ne všichni jej budou mít aktivní.

K ověření, že uživatel zadal správné heslo, jeho heslo ale přeci mít uložené potřebujeme. Nebo ne?

Hashování hesel

Hashování [hešování] je jednosměrný převod nějakých vstupních dat na jinou hodnotu. Pokud zahashujeme uživatelské heslo, získáme jeho otisk. Jedná se obvykle o řetězec zdánlivě nesouvisejících znaků a číslic a nelze z něj původní heslo zjistit. Např. pro heslo itNetwork1 bychom dostali následující řetězec:

$2a$12$tOhKwfjT91uV­XuMLf4lWYuYW8RE­Izn/Cm0QPJ2PK1­XPZpq2Wrbg7u

Místo hesla uživatele ukládáme vždy jen jeho otisk, ze kterého nelze původní heslo získat.

Hashovací algoritmy jsou kryptograficky navržené tak, že je nelze prolomit jinak než zkoušením všech kombinací. To při dobře zvoleném algoritmu a soli (viz dále) lze v rozumném čase provést jen v minimální míře. Kromě ukládání hesel se hashování využívá také např. pro elektronické podpisy nebo kryptoměny.

Ověření hesla pomocí otisků

Jak teď ale zjistíme, že uživatel zadal správné heslo? To je snadné. Z hesla, které uživatel zadal, spočítáme otisk. Ten porovnáme s otiskem, který máme uložený u daného uživatele v databázi. Pokud jsou otisky stejné, musel zadat i stejné heslo!

Takovouto autentizaci si můžeme představit, jako by si uživatel lehl do písku a my si vyfotili důlek, který po něm zůstal. Když přijde znovu, necháme ho znovu lehnout si do písku a porovnáme, zda důlek po něm vypadá stejně, jako důlek, co máme u jeho účtu. Pokud ano, jde o toho stejného člověka (pokud výrazně nepřibral, což se u hesla nestane :) ). Když nám někdo ukradne knihu s fotografiemi důlků, nikdy z ní nezjistí, jak vypadají obličeje lidí, kteří k nám chodí. Stejně tak, když nám někdo ukradne databázi webu s hashy hesel, nikdy nezjistí hesla našich uživatelů.

Následující 2 lidé mají v písku stejné otisky a jedná se tak o stejného člověka:

Otisk člověka v písku - Databáze a Hibernate ve Spring Boot - Blog Otisk člověka v písku - Databáze a Hibernate ve Spring Boot - Blog

A zde se někdo snaží vydávat za někoho jiného, otisky nesouhlasí:

Otisk člověka v písku - Databáze a Hibernate ve Spring Boot - Blog Otisk člověka v písku - Databáze a Hibernate ve Spring Boot - Blog

Hashování vs. šifrování

Hashování si nebudeme plést se šifrováním.

Šifrování je obousměrným převodem dané hodnoty a bylo by pak možné heslo zpětně získat. Hesla šifrují např. klíčenky, které potřebují dostat původní heslo, aby jej mohly odeslat do nějaké další služby. My heslo nikam neposíláme, pouze ověřujeme, že uživatel zadal to stejné. Proto jej nešifrujeme, ale hashujeme. Šifru lze dešifrovat, hash ne.

Další častou chybou je, že si lidé myslí, že hashe jsou unikátní. Pravděpodobnost je sice zanedbatelná, ale pro 2 různá hesla může hashovací funkce vygenerovat stejný hash. Pro ověření hesla to nijak nevadí, ale hashe bychom nikdy neměli používat jako unikátní identifikátory.

Slabiny hashování

Téměř na každý známý web byl již provedený hackerský útok, velmi často i úspěšný. Jak již bylo řečeno, hashovací algoritmy jsou jednocestné. To můžeme chápat tak, že část informací z původního hesla jednoduše zahazujeme. Hackeři jsou ovšem vynalézaví a stejně přišli na v zásadě 2 metody, jak původní heslo z otisku přeci jen získat. Stručně si je zde zmíníme, abychom věděli, na co si dávat pozor.

Slabina 1 - Algoritmus

Hashování je navržené tak, aby výpočet otisku počítači chvíli trval. Počítače se ovšem stále zrychlují. Pokud budeme používat zastaralé algoritmy jako např. md5, mohou hackeři jednoduše vyzkoušet všechna možná hesla kombinacemi znaků do určité délky. Z těchto hesel pak budou počítat otisky, dokud se nestrefí do toho, který máme uložený v databázi. U moderních algoritmů nelze na současných počítačích hashe takto rychle počítat.

Spring Boot Security má v sobě zabudované 2 algoritmy spjaté s hashováním hesel:

  • bcrypt – Moderní algoritmus za vývojáře řeší přidávání soli k heslu a případnou volbu hashovacího algoritmu, proto také tento algoritmus využijeme. Implementaci algoritmu lze najít ve třídě BCryptPasswordEncoder.
  • Argon2 – Ještě modernější alternativa k bcryptu. Implementaci algoritmu lze najít ve třídě Argon2PasswordEncoder.

U algoritmu lze obvykle nastavit i náročnost výpočtu (číslo 12 v ukázce heshe na začátku lekce). Čím větší bude, tím déle bude trvat otisk vypočítat. Není to ovšem ekvivalent bezpečnosti, příliš vysoká hodnota může způsobovat výkonnostní problémy aplikace.

Slabina 2 - Neosolené heslo

Určitě víte, že spoustu lidí používá hesla jako 123456 a podobně. I rozumněji zvolená hesla by se nám ovšem v databázi opakovala. S touto problematikou souvisí např. birthday paradox - Jaká myslíte, že je pravděpodobnost, že mají ve skupině 23 náhodně zvolených lidí dva lidé narozeniny ve stejný den? Je to 50 %.

Není tedy problém podle četnosti výskytu stejných otisků v databázi hesla hádat. Nebo mít na nejpoužívanější hesla předpočítané otisky na nejznámější algoritmy. Takovým databázím hashů se říká rainbow tables. Lze se jednoduše podívat, zda někdo náhodou nemá otisk "73cd1b16c4fb­83061ad18a0b29b9643a68d4­640075a466dc9e51682f84a8­47f5" a hned víme, že jeho heslo je "superman".

Z tohoto důvodu k heslu uživatele před výpočtem hashe ještě vždy něco připojíme, např. ID uživatele, čímž uživatelé i s nejhloupějšími hesly budou mít hashe, které nebudou v duhových tabulkách. Říkáme, že tím heslo přisolíme.

Solení hesel - Databáze a Hibernate ve Spring Boot - Blog

Sůl je obvykle také u každého uživatele jiný řetězec. Pokud si tedy 10 našich uživatelů nastaví heslo "qwerty", s použitím soli všichni budou mít jiný hash, jelikož se ke "querty" přidá nějaká další hodnota. Vytrvalý hacker, co si dá tu práci předpočítat pár častých hesel pro jednu naši sůl, tak nemůže výsledné hashe použít pro další uživatele a u každého musí začínat znovu.

Moderní algoritmy si sůl generují samy a ukládají si ji přímo do výsledku (část výsledné hodnoty hashovací funkce je otisk a část sůl). Nemusíme se tedy o nic starat. Je ovšem vhodné vždy ověřit, že to zvolený algoritmus dělá nebo se očekává, že sůl připojíme my.

V příští lekci, Blog ve Spring Boot - UserEntity a UserRepository, vytvoříme entitu pro uživatele a repositář se základními CRUD operacemi.


 

Předchozí článek
Blog ve Spring Boot - Validace registračního formuláře
Všechny články v sekci
Databáze a Hibernate ve Spring Boot - Blog
Přeskočit článek
(nedoporučujeme)
Blog ve Spring Boot - UserEntity a UserRepository
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
232 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity