Jak řešit bezpečné ukládání hesel v databázi

Tento článek je věnován spíše začínajícím vývojářům, kteří s danou problematikou nemají žádné zkušenosti. Proto, pokud jste již zkušenými programátory, omluvte jeho řekněme naivní přístup.

Přemýšleli jste někdy nad tím s jakými hesly se registrujete do různých služeb, kde je vyžadováno přihlášení? Někdo má pro tyto služby vyčleněný speciální email a heslo, velká většina laických uživatelů však často používá jako uživatelské jméno svůj email a jako heslo...své heslo (tedy i heslo k emailu, který byl použit při registraci). Tohoto se uživatelé dopouštějí s mylným doměním, že jejich heslo znají pouze oni. Ale v případě, kdy toto heslo odešlou registračním formulářem, zná ho i majitel služby kam se registrují. Po registraci je heslo spolu s přihlašovacím jménem uloženo do databáze a při opětovném přihlášení se kontroluje, zda uvedené jméno a heslo souhlasí s daným řádkem databáze. Tolik na úvod k této problematice a nyní se podíváme na způsoby ukládání hesel.

Nebezpečné ukládání hesel

Heslo je ukládáno v textovém tvaru (tedy řetězci "heslo123" bude v databázi odpovídat řetězec "heslo123"). Tento způsob je z hlediska vývojáře nejjednodušší, nicméně je nejnebezpečnější. V případě, že se někdo dostane k vaší databázi získá tak hesla ke všem účtům. Tuto techniku používají ty weby, které jsou Vám schopni zaslat zapomenuté heslo emailem (nemusí nutně platit, že heslo mají uloženo přímo v databázi ale originál hesla někde musí mít uschovaný).

Bezpečné ukládání hesel

Klíčem k bezpečnému ukládání hesel je takzvaná hashovací funkce, která pro každý řetězec předaný této funkci vrací jeho hash. Hash je naprosto jiný řetězce ze kterého je v rozumném čase nemožné získat původní řetězec. Hashovacích funkcí je v programovach jazycích dostupné několik různých funkcí. V jazyce PHP se jedná o např. následující:

  • MD5
  • SHA1

Algoritmus SHA1 pro řetězec "heslo123" funguje následovně:

sha1("heslo123")="849b28dcbe2c37b2c60d994e5dbd4b21535d0701"

Princip hashování hesel spočívá v tom, že do databáze je uložen pouze hash ukládaného hesla. Při kontrole hesla v průběhu přihlašování se postupuje tak, že se nejprve heslo převede na hash a ten se následně porovná s hashem uloženým v databázi. Pokud se shodují, bylo při přihlašování zadáno správné heslo.

V případě, že se někdo dostane k hasům uloženým v databázi, nemůže se pomocí nich přihlásit do jednotlivých uživatelských účtů.

Ještě bezpečnější ukládání hesel

Předchozí metoda vypadá na první pohled velmi bezpečně, ale co v okamžiku, kdy si někdo dá tu práci a pomocí procházení slovníku či generování náhodných řetězců sestaví převodní tabulku mezi "všemi možnými řetězci" a jejich hashi. V tomto případě již nebude tak složité odhalit původní heslo (pokud bude v převodní tabulce obsaženo). Z tohoto důvodu se hesla hashují se solí.

Sůl je v podstatě jakýkoli řetězec, který se k heslu připojí ještě před hashováním. Pro každého uživatele by měla být sůl odlišná. to způsobí, že výsledný hash dvou stejných hesel bude pro oba dva uživatele odlišný. Sůl je třeba si u každého uživatele pamatovat a použít ji opět při ověřování hesla.

Typicky se jako sůl používá uživatelské jméno, nebo jeho část.

Útok hrubou silou

Ani jedna z výše uvedených metod nedokáže předejít prolomení hesel pomocí útoku hrubou silou, tedy útoku, při kterém jsou vyzkoučeny všechny možné kombinace znaků v heslu. Před tímto útokem je třeba bránit se jinými způsoby, například omezením počtu možností chyného zadání hesla.