Uchovávání hesel ve webových aplikacích

Heslo francouzské revoluce „volnost, rovnost, bratrství“ se v případě webových aplikací příliš neujalo. Zpravidla je žádoucí, ne-li přímo nevyhnutelné, uživatele nějakým způsobem omezit a kastovat.

V této souvislosti se setkáváme se třemi základními pojmy: identifikace, autentizace a autorizace. Identifikace je prostá odpověď na otázku „kdo jsi?“ – pokud napíšete k tomuto článku komentář, budete požádáni, abyste prozradili své jméno. V tomto případě se vámi zadaná hodnota nijak neprověřuje, ale zpravidla bývá identifikace následována autentizací (někdy se tento proces nazývá též autentifikace). To je v podstatě odpověď na výzvu „dokaž to!“. Posledním krokem tohoto řetězce bývá proces autorizace, v němž se na základě známé identity uživatele a nějakého systému práv rozhoduje, jaké operace mu bude dovoleno vykonat.

V tomto článku nás bude zajímat autentizace, a to specificky autentizace pomocí hesla. Ve většině případů jest povinností tvůrce aplikace, aby se ve vlastní režii postaral o bezpečné uložení hesla. To lze zajistit různými způsoby.

Zdánlivě nejjednodušší způsob je prostě heslo tak jak je uložit do databáze. Jedná se také o způsob nejhorší a nejméně bezpečný. Vinou špatného zabezpečení serveru, chyby, podplacení správce nebo desítkami dalších způsobů může útočník získat přístup k databázi či jejím zálohám.

V takovém případě došlo k totální kompromitaci nejenom vašeho systému, ale též k ohrožení dalších účtů vašich uživatelů v systémech, se kterými nemáte nic společného. Velká část uživatelů totiž používá pro všechny systémy stejné heslo. Což je z hlediska bezpečnosti sice smutná, leč vcelku pochopitelná realita. Proto byste i v případě aplikace která není sama o sobě příliš důležitá, měli věnovat bezpečnému uložení hesel pozornost.

Šifrování

Jednou z možností je hesla před uložením do databáze zašifrovat. Tato možnost je jediná, kterou můžete použít v případě, že vámi používaný autentizační systém vyžaduje na serveru znalost hesla v otevřeném tvaru (například Digest authentication). S její implementací jsou ovšem spojeny značné obtíže, spočívající především v nezbytnosti nějak bezpečně uložit šifrovací klíč, který používáte. A nezapomenout ho pečlivě (a bezpečně) zazálohovat, protože pokud o něj přijdete, už nikdy žádného uživatele neověříte.

Bohužel, v podmínkách běžného komerčního hostingu je bezpečné uložení šifrovacího klíče v podstatě nemožné. ASP.NET sice má v tomto směru rozličné možnosti, leč ty jsou založeny na DPAPI (Data Protection API) a předpokládají možnost spuštění utility z příkazového řádku nebo možnost vykonání jistých poměrně privilegovaných operací.

Více informací:

Hashování

Ve většině případů (například pokud používáte Basic nebo Forms autentizaci) nepotřebujete správné heslo znát. Potřebujete mít pouze možnost ověřit si, že heslo je stejné, jako to správné. K tomuto účelu můžete s výhodou využít hashování.

Hashování je v podstatě výpočet kontrolního součtu. Slyšel jsem pro tento proces označení „matematická ráčna“, protože je jednosměrný: z daných dat spočítáte vždy stejný kontrolní součet (hash), ale neexistuje způsob, jak z hashe rekonstruovat zpět původní data.

Nejznámější a nejrozšířenější hashovací algoritmy jsou SHA1 a MD5. Před nedávnem prolétla odbornými i mainstreamovými médii zpráva, že tyto algoritmy byly prolomeny. Je to pravda, ale ne úplně – objevený mechanismus neumožňuje rekonstruovat z hashe původní text, ale spíše umožňuje nalezení dvojic dat, majících stejný kontrolní součet. Pro náš účel jsou tyto algoritmy stále použitelné, i když s ohledem na budoucnost je vhodné zamýšlet se nad použitím pokročilejších algoritmů, jako například SHA512.

Celková idea použití hashe pro ukládání hesel je taková, že v databázi uchováváte nikoliv hesla, ale jenim jejich hashe – kontrolní součty. Ověření hesla pak probíhá tím způsobem, že vypočítáte hash zadané hodnoty a výsledek se musí shodovat s uloženou hodnotou. Pokud se vaše databáze dostane do nepovolaných rukou, nezíská útočník hesla, ale toliko jejich hashe, které jsou mu teoreticky k ničemu, protože by je musel prolomit hrubou silou, tedy vyzkoušet všechny možné kombinace a spočítat pro ně hashe.

Prakticky ale zneužít hashe lze. Oproti obecným bezpečnostním zásadám a doporučením uživatelé používají hesla krátká a odhadnutelná, případně nalezitelná ve slovníku. Na Internetu jsou volně ke stažení soubory, které obsahují seznamy obvyklých slov a hesel a k nim odpovídající hashe. Útočníkovi pak stačí porovnat tyto hashe s databází získanou útokem a slabá hesla odhalí.

Hashování se solí

Z tohoto důvodu se obvykle doporučuje používat takzvaný hash se solí. Tato metoda spočívá v tom, že se k heslu přidá ještě nějaký další text, „sůl“ (anglicky „salt“) a teprve z toho se spočítá hash. Na rozdíl od šifrovacího klíče nevyžaduje sůl nijakou zvláštní ochranu a utajení. Sama o sobě je „sůl“ k ničemu, slouží pouze k zamezení možnosti použít předpočítané slovníky hesel.

Existují dva základní způsoby, jimiž lze „sůl“ použít. První je ten, že její hodnota je pro všechny uživatele v rámci aplikace stejná. Tak lze efektivně zabránit použití obecných slovníků předpočítaných hesel, ale pokud si útočník dá tu práci a spočítá si hesla s vaší solí, může pak takto vytvořený slovník použít proti všem uživatelským účtům.

Doporučený postup je tedy takový, že „sůl“ je generována zvlášť, pro každého uživatele. Náročnost prolomení jednoho konkrétního účtu tím sice zůstane nezměněna, ale případný úspěch nijak nepomůže útočníkovi v útoku na další uživatele.

Implementace hashování se solí

Pokud tedy chcete používat posledně uvedenou metodu, použijte následující postup.

Při vytváření uživatelského účtu:

  1. Vygenerujte náhodný řetězec, který se použije jako sůl (použijte třeba metodu Membership.GeneratePassword()). Na jeho délce příliš nezáleží, já osobně používám pět znaků.
  2. Spočítejte si hash z řetězce Heslo + Sůl.
  3. Do databáze uložte uživatelské jméno, sůl a vypočtený hash.

Při ověření přihlášení:

  1. Načtěte z databáze sůl k danému uživatelskému jménu.
  2. Spočítejte si hash z řetězce Heslo + Sůl.
  3. Porovnejte, zda se vypočtená hodnota shoduje s hodnotou hashe, uloženou v databázi.

Tento postup je zcela univerzální, můžete ho použít nezávisle na zvoleném hashovacím algoritmu.

A dva malé tipy na konec:

  • Ačkoliv se s hodnotami hashů obvykle setkáte jako s řetězcem šestnáctkových číslic (Base16 encode), jedná se nativně o prostý proud bitů. Pokud hash zakódujete metodou Base64, bude kratší.
  • Navíc je hash vždycky stejně dlouhý (jeho délka vyplývá z použitého algoritmu). Můžete tedy po zakódování Base64 odstranit zbytečné výplňové znaky (padding, „=“) a k uložení v databázi použít pole typu char s pevnou délkou a ne obvyklý varchar.
Titulek:
Text komentáře:
Vaše jméno:
Váš e-mail: (nebude zveřejněn)

WWW stránka:
Opište text z obrázku:
odpovědětodpovědět Gravatar

Náhdně generovaná sůl?

Osobne reseni s nahodnym generovanim stringu pro salt nepovazuji za nejvyhodnejsi reseni. Pokud utocnik ziska fyzicky pristup k DB, tak si muze snadno pridavat vygenerovane retezce. Videl bych reseni v tom, pridavat nahodny retezec na prezkacku (heslo"KNIHA" salt:"123" vysledek pro hash:"K1NI23HA"). To by mohlo zmast, ale prezto neodpada moznost, ze si utocnik hesla spocita.

Mnou navrhovana moznost je, ze pouzit nahodnou sul, heslo se melo nahodne poupravit, pricemz by bylo na vyber z nekolika(5) moznosti. A FCE, ktera by testovala jestli je user prihlaseny by testovala jestli je dobra. Tato moznost bude ale vytezovat DB i Aplikacni server.

odpovědětodpovědět Gravatar

RE: Náhdně generovaná sůl?

Nesouhlasím. Svůj účel splní přidání soli na pevné (známé) místo. Jde o to, že útočník nemůže použít předpočítané heslo, ale musí si ho spočítat sám, což hraničí s nemožným.

Vámi navržené řešení do systému vnáší prvek nejistoty, a navíc způsobuje, že se jako správné nebude jevit jedno heslo, ale pět hesel.

odpovědětodpovědět Gravatar

Nahodne generevana sul v membership provideru

Pouzivam klasicky membership provider a databazi aspnetdb. Kdyz nakouknu do tabulky aspnet_Membership tak je v ni sloupec - PasswordSalt. Znamená to, že membership provider umi sam o sobe implementovat heshovani se soli ?

odpovědětodpovědět Gravatar

RE: Nahodne generevana sul v membership provideru

Ano. Umí všechny tři varianty -plain, šifrované i hashované.

odpovědětodpovědět Gravatar

hash(jmeno+heslo)

Dobrý den, napadlo mě, co kdyby se použilo jako sůl uživatelské jméno. V databázi by se ukládalo uživ. jmeno a hash(heslo + jmeno). Odpadl by tedy jeden sloupec a taky možnost porovnávání hashů s nějakým slovníkem. Navic je jméno jedinečné, takže zastoupí i generování náhodných stringů.

Uživatelské jméno by se jako sůl jistě použít dalo. Může ovšem poskytovat menší obranu před slovníkovým útokem (typicky se jedná o smysluplné slovo) a úspora úložného prostoru a výpočetního výkonu je myslím v tomto rozsahu nepodstatná.

  • Altairis
  • Nemesis
  • Microsoft MVP
  • IIS
  • ASP.NET