webForumDet fria alternativet

Säkerhetsfråga

7 svar · 685 visningar · startad av startail

startailMedlem sedan sep. 2000155 inlägg
#1

Inte specifikt till PHP men jag tänkte jag skulle ställa en säkerhetsfråga till alla er här på webforum.

Jag vill spara mina användares lösenord säkert och använder därmed ett saltat lösenord specifikt till varje användare. Jag har läst runt litegranna och kollat på exempel, men tycker att folk gör det för lätt för sig ändå. Att bara salta och hasha en gång verkar för svagt. Som tex

$hash = md5($salt . $passwd);

Taget härifrån

Mitt förslag på användning är detta, och vad jag vill ha feedback på.

define('SALT_LENGTH', '10');
$salt = substr(md5(uniqid(rand(), true)), 0, SALT_LENGTH);  
$hash = sha1(md5($salt.md5(md5($password).$salt)));

Är detta att överdriva, eller är detta en riktigt bra funktion?
Saltet kommer sparas i databasen med användaren, men spelar ingen roll då om någon kommer över databasen (och denna kod) har flera timmar framför sig för varje steg i användarens lösenord.

SPiNMedlem sedan mars 20007 896 inlägg
#2

Det är overkill. Med ett unikt salt för varje användare blir den potentiella crackern tvungen att generera en regnbågstabell för varje användare. Att däremot få fram en regnbågstabell för sha1(md5()) istället för sha1(), är enkelt att komma runt. Att slumpa fram ett salt som är unikt för varje användare är en bra grej.

Den som sitter med PHP torde gilla öppen mjukvara, och inom FSF och OSI är ju "security by obscurity" enbart irriterande och inte alls säkrare. ;)

startailMedlem sedan sep. 2000155 inlägg
#3

Vad menar du med att det är enkelt att komma runt sha1() och sha1(md5()).
Borde det inte bli svårare, eller krongligare, för attackeraren att komma åt lösenorden för varje steg man lägger till en md5() som är unik varje gång? Varav jag gjorde den så komplex.

BrimbaMedlem sedan dec. 19995 875 inlägg
#4

Det är bra att använda sig av iterationer i samband med hashing. Man gör det inte enbart för att det skall 'se komplicerat och ut'. Och som i detta fallet där man endast gör det tre gånger så ser jag en liten fördel, men inte jättestor.

Det jag brukar vilja ha i ett lösenordssystem är dessa komponenter:

lösenord,användarsalt,systemsalt,iterationer,sammansättning,hashalgoritm,versionshantering

En annan sak jag noterar är att md5 används. md5 rekommenderas inte eftersom den är "knäckt". Använd Sha512 eller bättre istället.

Lösenord
Ditt system bör se till att användarna har valt ett bra lösenord. Du kan sätta riktlinjer i samband med registrering exempelvis. Minst 8 tecken, minst 1 siffra, minst en versal, ej endast versaler, etc.

Användarsalt
Ett långt salt för varje användare. 128 tecken är en bra start. Här skall hela teckenuppsättningen användas. Detta salt lagras förmodligen i databasen.

Systemsalt
Ett långt som är samma för alla användare (det kan dock variera även bland användare om du använder versioner). 128 tecken är en bra start. Här skall hela teckenuppsättningen användas. Detta är ett salt som är lagrat i applikationen. Ofta kanske säkerhetshålet gör att man kommer åt antingen databasen eller applikationskoden, men båda delar är inte lika vanliga. Därför vill man lägga ett salt i databasen och ett salt i applikationen.

Iterationer
Man vill göra många iterationer, kanske flera tusen. Detta gör man inte för att det i sig är jättemycket säkrare, utan man gör det för att hashningen av lösenordet skall ta lång tid. För när man kör brute force eller liknande så får man testa sig fram, och man vill att varje test för en eventuell hacker skall ta lång tid. Så även om han har alla komponen
r, det hashade lösenordet, alla salt och sammansättningen så skall det ta lång tid att få fram ursprungslösenordet.

Sammansättning
Hur man skapar sitt hashade lösenord kan variera, och det bör variera. Detta eftersom det för en hackare är en okänd komponent som behövs för att knäcka ett lösenord. Ibland vill man kanske köra hash(hash(password)+salt+systemsalt), ibland vill man köra hash(systemsalt+password+salt), och många gånger mycket mer komplext än mina två exempel. Här blandar du även in iterationerna. Du kan ju välja att lägga iterationerna på en liten del, eller på hela delen.

Hashalgoritm
Här finns mängder. MD5, sha1, sha512, etc. Du bör välja en som är känd (försök inte att bygga en egen). Eftersom det tar längre tid att hasha en sträng med sha512 än med sha1 så rekommenderas sha512 i de flesta fall.

Versionshantering
Du vill kunna byta algoritm vid behov. Kanske kör du på sha1 och när den sedan "knäcks" (eller datorerna blir snabbare så det går fort med brute force), så kanske du vill byta till en annan hashalgoritm.
En annan fördel är att man har olika versioner för olika användare, vilket gör att om en hackare lyckas komma över ett lösenord för en användare, så kan inte samma metod användas för att knäcka lösenordet för nästa användare.

spangoMedlem sedan juni 20008 205 inlägg
#5

Tilläggas bör också att din saltgenerering inte blir säkrare för att du hashar saltet. Är en hash inte saltad är den i stort inte säkrare än klartexten, så du kan i princip lika gärna köra med uniqid("", TRUE) för att få fram saltet. Du missar entropi som det är nu eftersom du bara tar de första tecknen från uniqid.

SPiNMedlem sedan mars 20007 896 inlägg
#6

Nja. Visst blir det krångligare, men enbart i tid mätt - inte så mycket i svårighetsgrad. Med enkelt att komma runt menade jag att det inte är några problem att generera en regnbågstabell för sha1(md5(fritt antal hash-funktioner här)) om man kan generera en för enbart sha1() (eller kanske har en tabell på lager till och med). Det är enbart krångligare i och med att det tar ett tag att skapa tabellen, inte att det blir svårare att få fram lösenorden.

För att skydda sina användare på bästa sätt bör man generera lösenord åt dom, inte låta dom välja själva, samt använda ett slumpat, unikt salt för varje användare (samt ett systemsalt som Brimba påpekar). Sen räcker det att använda en (1) hash-algoritm för att dölja lösenordet. Så länge man använder specialtecken, siffror och både stora/små bokstäver i det genererade lösenordet är det tidsmässigt omöjligt att få ut lösenord från hash:en - det krävs en ofantligt stor regnbågstabell om man nu ska försöka knäcka systemet.

Redigerat,
Ang. SHA vs. MD5 är Brimba på rätt spår. Tyvärr har en del databaser inte inbyggt stöd för SHA256 elle SHA512, t.ex. MySQL har inte stöd för SHA512. Vidare kan man tänka på att man kanske ska hasha lösenordet på serversidan, så att det inte skickas i klartext till databasen (för att undvika man-in-the-middle-attacker). Sitter databasen på samma server som serverside-tekniken är inte det en nödvändighet, men för utbyggbarhet kan man kanske överväga det ändå.

BrimbaMedlem sedan dec. 19995 875 inlägg
#7

Ja exakt. Ett salt på kanske 100 tecken är förmodligen ganska bra, om du hashar det innan användning så kanske det "bara" blir 32 tecken, och då utnyttjar du ju inte hela saltet.

startailMedlem sedan sep. 2000155 inlägg
#8

Tack för alla svar, det har givit mig lite att tänka på när jag designar min funktion för att spara lösenord med.

Att använda ett salt för varje användaren och ett systemsalt är något jag inte tänkte på, garanterat bra.

Sen kommer jag nog använda SHA512 direkt i koden, inte i MySQL.

Versioner av olika hashningar skall jag definitivt kolla på, då man kanske ändrar metod efterhand.

142 ms totalt · 3 externa anrop · v20260731065814-full.fb544a5a
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
139 ms — hämta tråd, inlägg och bilagor (db)