Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
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 10 - Bezpečnostní hrozby - Jak správně ukládat hesla v Node.js?

V minulé lekci, Dokončení API v Node.js - Metody GET a PUT, jsme modifikovali dokumenty metodou PUT a ukázali si, jak na požadavky GET s parametry :)

V našem Node.js kurzu se dostáváme k uživatelským oprávněním, a tudíž i 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 - Node.js - Serverový JavaScript

Hesla se do databáze neukládají

Pro ukládání hesel nejen do databáze platí úplně pro všechny technologie 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í, tedy kromě hesla např. i mobilní aplikací. 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 - Node.js - Serverový JavaScript Otisk člověka v písku - Node.js - Serverový JavaScript

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

Otisk člověka v písku - Node.js - Serverový JavaScript Otisk člověka v písku - Node.js - Serverový JavaScript

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.

Nejpoužívanějším algoritmem je v současné době Bcrypt. Jedná se o moderní algoritmus, který za vývojáře řeší i přidávání tzv. soli k heslu, proto také tento algoritmus využijeme.

U algoritmu lze obvykle nastavit i náročnost výpočtu. Čí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 - Node.js - Serverový JavaScript

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, Autentizace, autorizace a registrace uživatelů v Node.js, si vysvětlíme rozdíl mezi autentizací a autorizací a následně naprogramujeme registraci uživatelů.


 

Předchozí článek
Dokončení API v Node.js - Metody GET a PUT
Všechny články v sekci
Node.js - Serverový JavaScript
Přeskočit článek
(nedoporučujeme)
Autentizace, autorizace a registrace uživatelů v Node.js
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
94 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