Ukládání hesel
- Ukládejte hesla tak, aby je útočník nezískal ani v případě napadení aplikace nebo databáze
- Většina moderních jazyků a frameworků poskytuje funkce, které pomáhají hesla bezpečně ukládat
- Útočník může brute forcovat hashe offline
- Offline útoky je možné zpomalit výběrem takových hashovacích algoritmů, které jsou náročné na zdroje
- Použijte Argon2id s minimální konfigurací 15 MiB paměti, počtem iterací 2 a 1 stupněm paralelismu
- Použijte scrypt s parametrem minimálních nákladů na CPU / paměť 2^16, minimální velikostí bloků 8 (1024 bajtů) a stupněm paralelizace 1 v případě, že Argon2id není k dispozici
- Použijte work factor 10 nebo vyšší a limit 72 bajtů u starších systémů používajíc ích bcrypt
- Použijte PBKDF2 s work factor 310.000 nebo vyšším a nastavte interní hashovací funkci HMAC-SHA-256, pokud není vyžadována FIPS-140
- Zvažte použití pepření k zajištění dodatečné in-depth ochrany (ačkoli sám o sobě neposkytuje žádné další bezpečné vlastnosti)
Background
Hashování vs šifrování
- Hashování a šifrování jsou způsoby, jak udržet citlivá data v bezpečí
- Hesla by měla být téměř za všech okolností zahashována, nikoli zašifrována
- Heshování = jednosměrné, zahashovanou hodnotu nelze získat zpět (”dešifrovat” ji)
- Hashování je vhodné pro ověřování hesel
- I když útočník získá zahashované heslo, nemůže ho zadat do aplikace a přihlásit se
- Šifrování = obousměrné, původní hodnotu lze po zašifrování znovu dešifrovat a získat zpět
- Šifrování je vhodné pro ukládání dat (citlivých nebo osobních)
- V souvislosti s hesly by se šifrování mělo používat pouze ojediněle, když je nutné získat původní heslo
- Například pokud aplikace potřebuje heslo použít k ověření v jiném systému, který nepodporuje moderní způsob, jako je OpenID Connect
- Použijte alternativní architekturu, aby se předešlo ukládání hesel v zašifrované podobě, pokud je to možné
- Více informací najdete v OWASP cheat sheetu
Jak útočníci crackují hesla
- Ačkoliv hesla není možné “dešifrovat”, je za určitých podmínek možné je “prolomit”
- Vyberte heslo, o kterém si myslíte, že ho oběť zvolila (např.
myStrongPsw12_
) - Spočítejte jeho hash
- Porovnejte spočítaný hash s hashem oběti - pokud se shodují, “prolomili” jste heslo
- Tento postup se opakuje pro velký počet hesel
- K výběru těchto hesel lze použít různé metody
- Seznam hesel získaný z jiných napadených webů
- Brute force (zkoušení všech možných kandidátů)
- Slovník nebo seznam běžných hesel
- Díky vysokorychlostnímu hardwaru (GPU) a cloudovým službám jsou náklady na úspěšné prolomení hesla relativně malé
- Zejména nejsou-li dodrženy osvědčené postupy pro hashování
- Hesla uložená pomocí moderních algoritmů a s využitím osvědčených postupů jsou pro útočníka prakticky neprolomitelná
- Výběr moderního hashovacího algoritmu je zodpovědnost vývojáře
Koncepty pro ukládání hesel
Solení
- Sůl (salt) = jedinečný, náhodně vygenerovaný řetězec, který se přidává ke každému heslu v rámci hashování
- Protože je sůl pro každého uživatele jedinečná, musí útočník prolamovat hesla jedno po druhém pomocí příslušné soli
- Místo, aby jednou vypočítal hash a porovnával je s každým uloženým hashem
- Výrazně to ztěžuje prolomení velkého počtu hashů - potřebný čas roste přímo úměrně s počtem hashů
- Solení chrání před útočníkem, který předem vypočítá hashe nebo je vyhledá v databázi
- Díky solení není možné zjistit, zda mají dva uživatelé stejné heslo
- Moderní hashovací algoritmy jako jsou Argon2id, bcrypt a PBKDF2, automaticky hesla solí
- Při jejich použití nejsou potřeba žádné další kroky
Pepření
- Kromě solení lze použít i pepření (peppering)
- Jeho účelem je zabránit útočníkovi, aby byl schopen prolomit některý z hashů - pokud má přístup k databázi, zmocnil se jí, využil SQL injection atp.
- Jednou ze strategií je hashování hesel a následné šifrování symetrickým klíčem nebo HMAC před uložením (klíč funguje jako pepř)
- Strategie nijak neovlivňuje funkci hashování hesel
- Pepř je sdílený mezi uloženými hesly a není jedinečný jako sůl
- Na rozdíl od soli by pepř neměl být uložen v databázi
- Pepř je secret, takže by měl být uložený ve vaultu nebo HSM (Hardware Security Modules)
- Zvažte strategii rotace klíče stejně jako u jiných kryptografických klíčů
Work factors
- Počet iterací hashovacího algoritmu, které se provedou pro každé heslo
- Obvykle 2^(počet iterací)
- Účelem je učinit výpočet hashe nákladnějším, což snižuje rychlost a zvyšuje útočníkovi náklady v případě, že se pokusí heslo prolomit
- Work factor je často uložen ve výstupu hashe
- Při výběru je potřeba najít rovnováhu mezi bezpečností a výkonem
- Vyšší work factors ztíží prolomení hashe, ale také zpomalí proces přihlašování
- Pokud je work factor příliš vysoký, může se snížit výkon aplikace a útočník by to mohl využít k DoS útoku provedením velkého počtu pokusů o přihlášení, čímž vyčerpá CPU serveru
- Neexistuje žádné zlaté pravidlo - závisí na výkonu a počtu uživatelů aplikace
- Určení optimálního work faktoru bude znamenat experimentování
- Výpočet hashe by měl trvat méně než jednu sekundu
Upgrade work faktoru
- Lze jej v průběhu času zvyšovat s tím, jak se hardware stává výkonějším a levnějším
- Nejlepším přístupem je počkat, až se uživatel přihlásí a po úspěšném pokusu znovu zahashovat jeho heslo s novým work faktorem
- Různá hesla tedy budou mít různé work factors
- V závislosti na aplikaci může být vhodné odstranit starší hashe a vyžadovat, aby uživatelé při příštím přihlášení svá hesla obnovili, aby se zabránilo ukládání starších a méně bezpečných hashů
Hashovací algoritmy
- Moderní hashovací algoritmy jsou pomalé, oproti algoritmům jako je SHA1 nebo MD5, které byly navrženy jako rychlé
- Jejich pomalost závisí na work faktoru
- Webové stránky by neměly skrývat, jaký algoritmus používají
- Pokud používáte moderní algoritmus, mělo by být bezpečné je veřejně uvést
Argon2id
- Argon2 je vítěz soutěže Password Hashing Competition 2015
- Algoritmus má tři verze, ale používat by se měla verze Argon2id
- Jako minimum by měla být použita jedna z následujících konfigurací, která zahrnuje velikost paměti (m), minimální počet iterací (t) a stupeň paralelismu (p)
- m=37 MiB, t=1, p=1
- m=15 MiB, t=2, p=1
- Obě nastavení jsou rovnocenné z hlediska ochrany, kterou poskytují
- Jediným rozdílem je kompromis mezi využitím procesoru a RAM
scrypt
- scrypt je funkce pro odvozování klíčů na základě hesla
- Nové systémy by vždy měly zvážit Argon2id, ale ve starších systémech se hodí právě scrypt
- Jako minimum by se měla použít jedna z následujících konfigurací, která zahrnuje parametr minimálních nákladů na procesor / paměť (N), velikost bloku (r) a stupeň paralelismu (p)
- N=2^16 (64 MiB), r=8 (1024 bytes), p=1
- N=2^15 (32 MiB), r=8 (1024 bytes), p=2
- N=2^14 (16 MiB), r=8 (1024 bytes), p=4
- N=2^13 (8 MiB), r=8 (1024 bytes), p=8
- N=2^12 (4 MiB), r=8 (1024 bytes), p=15
- Obě nastavení jsou rovnocenné z hlediska ochrany, kterou poskytují
- Jediným rozdílem je kompromis mezi využitím procesoru a RAM
bcrypt
- bcrypt by měla být hned druhou volbou pokud není k dispozici Argon2id
Limity
- U většiny implementací je maximální délka vstupu 72 bajtů
Pre-hashing hesel
- Alternativním přístupem je pre-hashování hesla pomocí rychlého algoritmu (SHA-256) a následné zahashování tohoto hashe
bcrypt(base64(hmac-sha256(data:$password, key:$pepper)), $salt, $cost)
- Jde o nebezpečný (ale běžný) postup
- Je třeba se mu vyhnout z důvodu password shucking a dalších problémů spojených s kombinací bcrypt a jiných funkcí
PBKDF2
- PBKDF2 je doporučován NISTem a jeho implementace je ověřena systémem FIPS-140
- Měl by být upřednostňovaným algoritmem, pokud jsou tyto algoritmy vyžadovány
- PBKDF2 vyžaduje zvolení hashovacího algoritmu
- HMAC-SHA-256 je doporučován NISTem
- Work factor je implementován prostřednictvím počtu iterací, které by měly být nastaveny odlišně v závislosti na použitém hashovacím algoritmu
- PBKDF2-HMAC-SHA1: 720 000 iterací
- PBKDF2-HMAC-SHA256: 310 000 iterací
- PBKDF2-HMAC-SHA512: 120 000 iterací
- Obě nastavení jsou rovnocenné z hlediska ochrany, kterou poskytují
- Heslo bude automaticky přehashováno, pokud je funkce použita s HMAC a heslo je delší než velikost bloku funkce
- Dobrá implementace provede tento krok před nákladnou iterační fází
- Některé implementace však provádějí konverzi při každé iteraci
- To způsobuje, že hashování dlouhých hesel je výrazně draž ší než hashování krátkých hesel
- Existuje zde potenciální DoS zranitelnost (jako např. v Djangu roku 2013)
Upgrade starších hashů
- V případě aplikací používajících starší, méně bezpečné hashe (MD5, SHA-1), by tyto hashe měly být aktualizovány na moderní algoritmy, jako je popsáno výše
- Při dalším zadávání hesla uživatelem (obvykle při přihlašování), by mělo být heslo znovu zahashováno moderním algoritmem
- Dobrým postupem je také vypršení platnosti aktuálního hesla a požadování nového po expiraci
- Tento přístup však znamená, že stará hesla budou uložena v databázi, dokud se uživatel znovu nepřihlásí
- Tomu se jde vyhnout následovně
- Použití stávajících hashů jako vstupů pro bezpečnější algoritmy
md5($password)
→bcrypt(md5($password))
- Vrstvením hashů se vyhnete znalosti původního hesla
- Tento přístup může usnadnit prolomení hesel
- Tyto hashe by měly být při příštím přihlášení nahrazeny přímými hashi
- Ujistěte se, že upgrade hashovacího algoritmu je co nejjednodušší
- Počítejte s kombinací starých a nových hesel pro přechodné období
- Použití kombinace algoritmů hashování je snazší, pokud jsou algoritmus a work factor uloženy spolu s heslem (např. PHC řetězci)
- Použití stávajících hashů jako vstupů pro bezpečnější algoritmy
Mezinárodní znaky
- Ujistěte se, že je hashovací knihovna schopna přijímat širokou škálu znaků a je kompatibilní se všemi kódovými znaky Unicode
- Uživatelé by měli mít možnost používat celou škálu znaků, které jsou na moderních zařízeních k dispozici
- Měli by mít možnost vybírat hesla z rýzných jazyků a piktogramů
- Snižte entropy před hashováním uživatelského hesla
- Hashovací knihovny musí být schopny přijímat
NULL
bajt