Uppdaterad | Publicerad
Hasha lösenord rätt - Återkomsten
För fem år sedan publicerade vi en artikel om hur lagring av lösenord bör implementeras. Vad har hänt under dessa fem år?
En sak är lätt att konstatera: Världen lyssnade varken på oss eller andra som predikade om säker lösenordshantering. Antalet lösenordsläckage har varit många under dessa fem år och vi känner inte till något fall där den drabbade organisationen hade lagrat lösenorden på ett säkert sätt. Här är några exempel:
-
LinkedIn: Mer än sex miljoner osaltade lösenordshashar stals från LinkedIn sommaren 2012. Detta ledde till att de blev nominerade till The Pwnie Award med motiveringen "What has 2500 employees, over 90 million users, no CSO, and hates salt?".
-
Sony: 77 miljoner användaruppgifter, inklusive osaltade lösenordshashar, stals från Sony PlayStation Network 2011. Som om det inte vore nog läckte en miljon lösenord från SonyPictures.com.
Dessa lösenord lagrades i klartext. -
RockYou: Spelföretaget RockYou läckte mer än 32 miljoner lösenord i klartext vintern 2009. Dessa lösenord är publikt tillgängliga och är något av en standardreferens för studier av hur dåliga lösenord användare väljer. Listan är också populär för att knäcka lösenordshashar.
-
Stratfor: Säkerhetsföretaget Stratfor läckte 860 160 stycken MD5-hashade lösenord 2011.
-
Evernote: I mars 2013 råkade Evernote ut för ett intrång och valde att återställa 50 miljoner lösenord. Lösenorden lagrades som saltade MD5-hashar.
-
I Sverige har ett antal webbplatser drabbats, exempelvis gratisbio.se (210 000 lösenord i klartext), bloggtoppen.se (94 000 osaltade MD5-hashar) samt familjeliv.se (120 000 hashar i okänt format).
Att lagra lösenord i klartext eller som osaltade MD5-hashar var ignorant och på gränsen till pinsamt redan 2008. Tyvärr har det inte hänt så mycket sedan dess.
Vad är det för fel på MD5 och SHA-1?
Två populära kryptografiska hashfunktioner som tyvärr fortfarande används för att hasha lösenord är MD5 och SHA-1. Vitsen med att hasha lösenordet är att det är svårt att köra hashningen åt andra hållet och få fram lösenordet från hashvärdet. Både MD5 och SHA-1 är svåra att "köra baklänges", och det vanligaste sättet att knäcka en lösenordshash är därför genom en så kallade ordboksattack. Attacken går ut på att hasha kandidater från en lista över potentiella lösenord och sedan jämföra med lösenordshashen som ska knäckas. Om hasharna är lika har lösenordet hittats. Problemet är att både MD5 och SHA-1 är förhållandevis snabba och kan dessutom köras i moderna grafikkort. Exempelvis kan en dator med ett modernt grafikkort generera runt 7 miljarder MD5-kandidater per sekund.
Säkrare alternativ: PBKDF2, bcrypt och scrypt
Genom att göra varje hashning lite mer resurskrävande blir en råstyrkeattack ("brute force") flera magnituder mer tidskrävande. Exempelvis kan hashningen köras flera gånger. I PBKDF2 rekommenderas minst 1000 iterationer (10000 rekommenderas av NIST 2016) av hashningen, vilket gör en ordboksattack ungefär 1000 gånger långsammare. Det är viktigt att denna så kallade "work factor" går att skruva upp för att matcha utvecklingen av hårdvaran. En bra tumregel är att hashningen ska ta åtminstone 100 ms vid en interaktiv inloggning. I följande standarder kan "work factor" ställas in:
-
PBKDF2: Mycket spridd och beprövad standard som finns implementerad i en rad olika språk, exempelvis Java, C, C#, Python, Ruby och PHP. PBKDF2 (Password-Based Key Derivation Function 2) finns specificerad i RFC 2898 och fungerar tillsammans med olika hashfunktioner, till exempel MD5 och SHA-1. I PBKDF2 går det att specificera antalet iterationer av hashningen samt salt.
-
bcrypt: Använder sig av algoritmen Blowfish och det faktum att nyckelinitieringen i Blowfish är förhållandevis CPU-intensivt. Är inte lika spridd som PBKDF2 men finns till en rad olika språk, exempelvis Java, C, C#, Python, Ruby och PHP. Ett kvalitetsbevis är att OpenBSD använder sig av bcrypt.
-
scrypt: Både PBKDF2 och bcrypt kan implementeras i specialdesignad hårdvara, exempelvis i ASIC-kretsar, vilket skulle göra råstyrkeattacker betydligt mer effektiva. För att råda bot på detta problem är scrypt förutom CPU-intensiv även minneskrävande. Minneskravet gör den svår att implementera i hårdvara. scrypt är på pappret den mest säkra av de tre algoritmerna men också den minst spridda, vilket kan bero på att den är nyast. C-, Java- och Python-implementationer av scrypt finns tillgängliga.
Glöm inte saltet
Med salt menas att ett slumptal hashas tillsammans med lösenordet. Saltet är inte hemligt och kan lagras i klartext tillsammans med användarnamnet. Det är viktigt att saltet är slumpmässigt, tillräckligt långt samt unikt per användare. Fördelarna med salt är följande:
-
Attacker med "rainbow tables" blir svårare. Denna attackmetod är en ordboksattack men där hasharna är genererade i förväg. En attack tar mindre beräkningskraft eftersom varje kandidat inte längre behöver hashas, men å andra sidan krävs mer minne. Om ett salt har en längd på exempelvis 128 bitar krävs 2^128 förgenererade hashar, vilket blir så pass många att en "rainbow tables"-attack inte längre är effektiv. På senare tid har "rainbow tables" gått lite ur modet, eftersom moderna grafikkort är så pass snabba att vinsten med att mindre beräkningskraft krävs inte vägs upp av det ökade minneskravet.
-
Två användare med samma lösenord får olika hashar. I stora system finns alltid användare som väljer samma lösenord och dessa får samma hashvärde om inget salt används.
Salt ska alltså användas men ger inget större extra skydd.
Vad kan jag som användare göra?
Användare av webbtjänster måste alltid räkna med att ens lösenord kan komma att exponeras. Samma lösenord ska därför aldrig användas till mer än en tjänst. Återvinning är bra men inte när det gäller lösenord. För att klara sig helskinnad från ett lösenordsläckage måste lösenordet vara svårt att knäcka, dvs tillräckligt långt och "svårgissat". Många användare underskattar en råstyrkeattack ("brute force") där alla teckenkombinationer gås igenom. Att exempelvis testa alla alfanumeriska tecken med en längd på 7 tecken då saltade SHA-1-hashar används tar en dryg timme. Att testa alla gemener på 9 tecken tar drygt ett dygn. Välj därför ett lösenord som är åtminstone 12 tecken eller längre och blanda gemener, versaler, siffror och specialtecken. Att definiera ett "svårgissat" lösenord är inte helt lätt. Helt klart är att ord i ordböcker bör undvikas, och att lägga på ett numeriskt prefix eller suffix hjälper föga. Bästa rådet är att vara kreativ och originell.
Security Through Obesity
Jeremy Spilman har föreslagit en ny och lovande metod som bygger på konceptet med det skämtsamma namnet "security through obesity". Användarnamn och salt lagras tillsammans, men hashvärdet är inte knutet till en användare utan lagras i en tabell med alla hashvärden. För att kontrollera ett lösenord vid inloggning görs följande:
- Användaren anger användarnamn och lösenordet.
- Saltet hämtas från användarnamnet.
- Lösenordet + salt hashas.
- Finns hashvärdet i tabellen? Om ja är inloggningen korrekt, annars inte.
Nu kommer det fiffiga: Tabellen med hashvärden kan fyllas med falska värden vars enda syfte är att skapa en stor tabell. En hashtabell på exempelvis 1 TB gör livet svårare för angriparen på flera sätt:
-
Det tar tid och är besvärligt att ladda ner en så pass stor fil.
-
Detektion blir lättare. En "fläskig" fil triggar förhoppningsvis många larm, exempelvis i en IDS eller WAF. För att underlätta upptäckt kan signaturer skapas från vissa hashar.
-
Mer resurser krävs av angriparen vad det gäller bandbredd och minne. Attacken tar även längre tid.
Mer information:
A Look at Security Through Obesity
New developments in password hashing: ROM-port-hard functions
Övrigt att tänka på
Fallgroparna är många vid implementation av lösenordsautentisering. Tänk på följande:
-
Hitta inte på något eget: Använd en beprövad algoritm och ett välkänt klassbibliotek. Undvik att implementera något själv även om algoritmen är känd. Annars kan det gå som för Cisco som misslyckades med att implementera PBKDF2 i IOS.
-
Bevara versaler och gemener: Konvertera aldrig lösenordet till exempelvis versaler eftersom då minskar antalet kombinationer drastiskt. Windows protokollet LANMAN gör just detta, vilket är en av anledningarna till att det är sårbart.
-
SSL kryptering: Skicka aldrig loginuppgifterna okrypterade. Överväg att kryptera hela session.
-
Felmeddelande: Använd aldrig olika felmeddelanden beroende på om det är användarnamnet som är fel eller lösenordet. Då kan nämligen angriparen få fram användarnamn.
-
Loggning: Logga alla misslyckade inloggningsförsök men logga aldrig angivet lösenord.
-
Bortglömt lösenord: Undvik frågor så som "vad hette din mamma som ogift?". Svaren är lättgissade och kortsluter starka lösenord. Ett bättre alternativ är att e-posta ett nygenererat lösenord till en tidigare angiven adress. (Bättre alternativ har tagits fram och finns att läsa hos OWASP: https://www.owasp.org/index.php/Forgot_Password_Cheat_Sheet)
-
Lösenordspolicy: Det kan vara värt att införa en policy som styr minimilängd, förekomst av siffror och specialtecken med mera. Det angivna lösenordet skulle också kunna kontrolleras mot en ordlista. Var försiktig med att sätta en livslängd på lösenordet. Användare hatar att byta lösenord och tenderar att rotera gamla lösenord eller börja använda svaga lösenord om de tvingas byta allt för ofta.
-
Online-attacker: För att undvika ordboksattacker mot inloggningssidan bör fördröjningar och inaktiveringar läggas in. Exempelvis kan ett konto inaktiveras i 15 minuter efter 10 misslyckade inloggningsförsök. Tyvärr kan denna metod användas för att stänga ute legitima användare, varför metoden bör användas med måtta.
Skulle råden i denna artikel kunnat förhindra exempelvis LinkedIn-attacken? Nej, men skadan skulle ha blivit mindre då färre lösenord skulle ha knäckts. Att förhindra att en angripare kommer åt lösenordsdatabasen, exempelvis genom att använda "sql injection", är högsta prioritet. Men det gäller att ha god säkerhet på alla nivåer för att minska skadan, och därför är säker lösenordshantering viktigt.
Mer information
Läs gärna min ursprungliga artikel då den tar upp aspekter som inte tas upp här:
Hasha lösenord rätt
En mycket bra historisk exposé i ämnet är skriven av Solar Designer och Simon Marechal:
Password security: past, present, future
För den som vill veta vad angriparna ägnar sig åt kan följande Defcon-presentation rekommenderas:
Defcon 2012: Cryptohaze Cloud Cracking by Bitweasil
För en mindre summa pengar kan vilken lekman som helst knäcka lösenordshashar:
CloudCracker
Till slut, en liten sång för att pigga upp:
Give it some salt
Vad tyckte du om artikeln? Skicka gärna ett mejl: cert@cert.se
/Tor Johnson, CERT-SE