Permalänk
Avstängd

Registrering inloggning php

Hej
Jag har skrivit en kod som ska registrerarar användare. Jag testar lite saker tillexempel e-mail, längd på användarnamn, lösen och mail. Problemet är att ibland står det att mailen har förmåga tecken utan att det överstiger 50 tecken, som är max.

<?php require ('connects.php'); function register($error_message){ if(isset($_POST['user'])&&isset($_POST['mail'])&&isset($_POST['password'])&&isset($_POST['rep_password'])){ if(!empty($_POST['user'])&&!empty($_POST['mail'])&&!empty($_POST['password'])&&!empty($_POST['rep_password'])){ $user = trim($_POST['user']); $mail = trim($_POST['mail']); $password = trim(md5($_POST['password'])); $rep_password = trim(md5($_POST['rep_password'])); $pattern_email = '/^(.+)@(.+).([a-ö]{2,3})$/'; if($user<=30&&$password<=50&&$mail<=50){ if(preg_match($pattern_email,$mail)){ if($rep_password === $password){ $insert = "INSERT INTO `brommund_se`.`users` (`id`, `username`, `password`, `mail`) VALUES ('','$user','$password','$mail')"; if(mysql_query($insert)){ header('Location: http://www.google.se'); }else{ $error_message[] = 'Kunde inte registrera! Försök igen.'; } }else{ $error_message[] = 'Lösenorden matchar inte!'; } }else{ $error_message[] = 'Skriv in en giltig e-postadress!'; } }else{ if($user>30){ $error_message[] = 'Användarnamnet är för långt (max 30 tecken)!'; } if($password>50){ $error_message[] = 'E-postadressen är för lång (max 50 tecken)!'; } if($mail>50){ $error_message[] = 'Lösenordet är för långt (max 50 tecken)!'; } } }else{ $error_message[] = 'Fyll i alla fält!'; } } return $error_message; } ?>

//Andreas

Permalänk
Medlem

Först, så gör du om lösenordet till en md5 hash innan du gör kontrollerna vilket gör att $password alltid kommer ha samma antal tecken.

För det andra så kollar du om _värdet_ är större än 50 och inte antalet tecken. Använd funktionen strlen för att kolla antalet tecken.

Skickades från m.sweclockers.com

Permalänk
Avstängd

Det är klart, dumt fel utav mig.

Permalänk
Legendarisk
Skrivet av Pandy95:

Hej
Jag har skrivit en kod som ska registrerarar användare. Jag testar lite saker tillexempel e-mail, längd på användarnamn, lösen och mail. Problemet är att ibland står det att mailen har förmåga tecken utan att det överstiger 50 tecken, som är max.

<?php require ('connects.php'); function register($error_message){ if(isset($_POST['user'])&&isset($_POST['mail'])&&isset($_POST['password'])&&isset($_POST['rep_password'])){ if(!empty($_POST['user'])&&!empty($_POST['mail'])&&!empty($_POST['password'])&&!empty($_POST['rep_password'])){ $user = trim($_POST['user']); $mail = trim($_POST['mail']); $password = trim(md5($_POST['password'])); $rep_password = trim(md5($_POST['rep_password'])); $pattern_email = '/^(.+)@(.+).([a-ö]{2,3})$/'; if($user<=30&&$password<=50&&$mail<=50){ if(preg_match($pattern_email,$mail)){ if($rep_password === $password){ $insert = "INSERT INTO `brommund_se`.`users` (`id`, `username`, `password`, `mail`) VALUES ('','$user','$password','$mail')"; if(mysql_query($insert)){ header('Location: http://www.google.se'); }else{ $error_message[] = 'Kunde inte registrera! Försök igen.'; } }else{ $error_message[] = 'Lösenorden matchar inte!'; } }else{ $error_message[] = 'Skriv in en giltig e-postadress!'; } }else{ if($user>30){ $error_message[] = 'Användarnamnet är för långt (max 30 tecken)!'; } if($password>50){ $error_message[] = 'E-postadressen är för lång (max 50 tecken)!'; } if($mail>50){ $error_message[] = 'Lösenordet är för långt (max 50 tecken)!'; } } }else{ $error_message[] = 'Fyll i alla fält!'; } } return $error_message; } ?>

//Andreas

if($user<=30&&$password<=50&&$mail<=50){

På den här raden jämför du ifall $user, som är ett namn i form av en sträng, är mindre än eller lika med heltalet 30, och detsamma för lösenord och email. Vad som händer här är att PHP försöker omvandla namnet till ett heltal för att dessa olika typer ska gå att jämföra, och du får därför varierande resultat. Istället måste du kontrollera strängens längd via strlen, eller mb_strlen om du använder ett multibytecharset. $password kommer alltid vara 128b lång så den behöver du inte kontrollera alls, vill du kontrollera att lösenordet uppfyller några särskilda krav måste detta ske innan du kör det genom hashfunktionen. Använd gärna whitespace för att göra koden mer lättläst med.

if(strlen($user) <= 30) {

/^(.+)@(.+).([a-ö]{2,3})$/

Rangen i det här regexpet gör inte vad du tror, a-ö betyder inte alla tecken i vårat svenska alfabet utan alla tecken mellan dessa två positioner i den teckentabell du använder dig av. Email bör inte valideras med hjälp av regex alls, PHP har inbyggda funktioner för att hjälpa till med det, men om du absolut vill så finns det ett korrektare regex här.

if(filter_var($email, FILTER_VALIDATE_EMAIL) !== false) { /* ... */ }

$insert = "INSERT INTO `brommund_se`.`users` (`id`, `username`, `password`, `mail`) VALUES ('','$user','$password','$mail')"; if(mysql_query($insert)){

Du bör inte skicka en tom sträng som ID, uteslut det helt och hållet från din query om det är en auto increment. Du bör även använda dig av mysqli eller PDO istället för den gamla mysql-modulen när du ansluter till mysqldatabaser, de två nyare modulerna har exempelvis stöd för prepared statements som hjälper dig att skriva säkra databasfrågor. Notera att detta bara påverkar hur du ansluter till databasen, mysqlservern berörs inte. Om inte har tillgång till dessa så måste du escapa all användardata manuellt, och gärna via sprintf för att hålla koden läsligare:

$insert = sprintf( 'INSERT INTO brommund_se.users (username, password, mail) VALUES("%s", "%s", "%s");', mysql_real_escape_string($user), mysql_real_escape_string($password), mysql_real_escape_string($mail) );

Gör du inte detta kan användaren skicka fragment av databasfrågor direkt till din server, och köra helt andra kommandon än vad du har tänkt dig. Se wikipedia för en introduktion till sql-injektion. Rekommenderar dock att du ser över alternativen, och har i åtanke att alla guider som rekommenderar mysql_-funktionerna är utdaterade (även om de för den skull kan innehålla annan information som fortfarande är relevant).

header('Location: http://www.google.se');

När man skickar en location-header vill man vanligen avbryta scriptet direkt efteråt. Notera att resten av scriptet kommer köras som vanligt och att besökarens browser laddar nästa sida först efter att allt annat är klart. Det kanske är vad du har tänkt dig, kanske inte.

header('Location: http://www.google.se'); die();

?>

Man bör heller aldrig avsluta PHP-scripts med ?> eftersom att det riskerar att lämna whitespace på slutet av filerna som kan skickas innan eventuella headers och orsaka en flora av olika problem för ditt program. Dessutom är det mer att skriva än om man låter bli. Använd bara slut-taggarna om du måste fortsätta med annat innehåll efteråt, exempelvis i HTML-templates.

Visa signatur

Abstractions all the way down.

Permalänk
Avstängd

Tack Tunnelsork väldigt hjälpsamt svar. Har en till fråga. En md5 hash är ganska lätt att dekryptera, men om man hashar hashen så blev det genast mycket svårare märkte jag, utav misstag. Så jag undrar finns det någon nackdel med att hasa en hash?

Permalänk
Legendarisk
Skrivet av Pandy95:

Tack Tunnelsork väldigt hjälpsamt svar. Har en till fråga. En md5 hash är ganska lätt att dekryptera, men om man hashar hashen så blev det genast mycket svårare märkte jag, utav misstag. Så jag undrar finns det någon nackdel med att hasa en hash?

Ja, det ökar risken för kollisioner (olika input som ger samma resultat). Du vill ha en långsam algoritm med saltade lösenord, det lättaste är att bara använda sig av crypt() och blowfish som hjälper dig med allt detta.

http://en.wikipedia.org/wiki/Key_stretching
http://en.wikipedia.org/wiki/Salting_(cryptography)

Visa signatur

Abstractions all the way down.

Permalänk
Avstängd
Skrivet av Tunnelsork:

Ja, det ökar risken för kollisioner (olika input som ger samma resultat). Du vill ha en långsam algoritm med saltade lösenord, det lättaste är att bara använda sig av crypt() och blowfish som hjälper dig med allt detta.

http://en.wikipedia.org/wiki/Key_stretching
http://en.wikipedia.org/wiki/Salting_(cryptography)

Är det så här du menar att jag kan göra:
$CRYPT_BLOWFISH = $2a$07$usesomesillystringforsalt$;
$password = "pass1234";
$safe_password = crypt($password, $CRYPT_BLOWFISH);

Det kommer vara säkrare en md5?

Har sätt att man ska göra en random CRYPT_BLOWFIH, men om jag gör det så kommer krypteringen att bli olika fast man krypterar samma ord. Hur löser man det?

Permalänk
Legendarisk
Skrivet av Pandy95:

Är det så här du menar att jag kan göra:
$CRYPT_BLOWFISH = $2a$07$usesomesillystringforsalt$;
$password = "pass1234";
$safe_password = crypt($password, $CRYPT_BLOWFISH);

Det kommer vara säkrare en md5?

Har sätt att man ska göra en random CRYPT_BLOWFIH, men om jag gör det så kommer krypteringen att bli olika fast man krypterar samma ord. Hur löser man det?

Vet inte vad du menar med "random CRYPT_BLOWFISH", men bifogar ett enkelt exempel på hur du kan hasha och testa lösenord med crypt.

<?php function makeSalt($len) { $alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; $salt = ""; for($i = 0, $c = strlen($alphabet) - 1; $i < $len; ++$i) { $salt .= $alphabet[mt_rand(0, $c)]; } return $salt; } function hashPassword($password, $workfactor = 8) { return crypt($password, sprintf('$2a$%\'02d$%s$', $workfactor, makeSalt(22) )); } function testPassword($password, $oldHash) { return crypt($password, $oldHash) === $oldHash; } $password = "foobar"; $hash = hashPassword($password); $test = testPassword($password, $hash); header("Content-type: text/plain; charset=UTF-8"); echo "Lösenord: ".$password."\n"; echo "Hash: ".$hash."\n"; echo "Test: ".($test ? "OK" : "FEL")."\n";

Skickades från m.sweclockers.com

Visa signatur

Abstractions all the way down.

Permalänk
Medlem

$password = trim(md5($_POST['password'])); $rep_password = trim(md5($_POST['rep_password']));

1) Indentera koden så att likamedstecknena är på samma rad. Ser bättre ut.
2) Trim är onödigt att köra på en md5 hash. Kommer aldrig bli space/tab från funktionen md5().
3) ANVÄND SALT!!, samt en långsammare hash metod eller kör metoden 10000000 gånger (kör ej för många gånger, då det tar för mycket kraft på servern).

$salt = "s<ljkh39odu908#U@[£${@£$€3952KSsd-?´?=+80@£€[€@3]}]; $password = hash('sha512', $salt . $_POST['password']); $rep_password = hash('sha512', $salt . $_POST['rep_password']);

Ännu säkrare:

$password = protectMyPassword($_POST['password']); $rep_password = protectMyPassword($_POST['rep_password']) function protectMyPassword($passwd) { $salt = "s<ljkhE3<>9odu90--..,¨'¨¨8#U@[£${@£$€3952KSsd-?´?=+80@£€[€@3]}]"; for ($i=100000; $i > 0; $i--) { $passwd = hash('sha512', $salt . $passwd); } return $passwd; }

Visa signatur

Programmerare -> PHP | HTML | CSS | JS | Java.

Permalänk
Avstängd

Tack både Tunnelsork och Sony? för bra svar, tror jag börjar förstå hur man ska kryptera på bra sätt. Men jag har läst att man kan skapa ett random salt till varje lösenord. Men problemet är ju då att jag måste ha samma salt när jag ska logga in med användaren, för jag måste kryptera på samma sätt.

Hur kan man spara saltet, man kan ju inte bara ha det skrivet rakt upp och ner i databasen. Har funderat på om man kan sätta delar utav saltet i början och i slutet utav det klarkrypterade lösenordet med ett speciellt mönster. Sen när man ska använda saltet använder man subst för att få saltet, skulle det fungera?

Permalänk
Legendarisk
Skrivet av Pandy95:

Tack både Tunnelsork och Sony? för bra svar, tror jag börjar förstå hur man ska kryptera på bra sätt. Men jag har läst att man kan skapa ett random salt till varje lösenord. Men problemet är ju då att jag måste ha samma salt när jag ska logga in med användaren, för jag måste kryptera på samma sätt.

Hur kan man spara saltet, man kan ju inte bara ha det skrivet rakt upp och ner i databasen. Har funderat på om man kan sätta delar utav saltet i början och i slutet utav det klarkrypterade lösenordet med ett speciellt mönster. Sen när man ska använda saltet använder man subst för att få saltet, skulle det fungera?

Syftet med ett salt är att göra varje hash unikt även om användaren använder ett vanligt lösenord, eller flera användare i databasen använder sig av samma inloggning (därför ska alla ha ett eget slumpmässigt salt). På det sättet kan man inte slå upp hashen i en tidigare skapad lista (se rainbow tables) utan tvingas genomföra upprepade gissningar för varje lösenord. Saltet fyller sin funktion även om det är känt, och det är inga problem att lagra det i klartext i databasen.

Att komplicera lagringen av saltet kommer ha tveksam effekt. Eventuella hackers kommer antagligen ha registrerat konton med kända lösenord som kan hjälpa till att avslöja hur de lagras, och har någon kommit åt databasen är det sannolikt att de har kommit över koden också. Du kan inte anta att det gör mer än fördröjer gissningarna.

Det är betydligt viktigare att öka tiden det tar att göra varje gissning (key stretching). För din server gör det marginell skillnad eftersom att lösenordshashande är en relativt liten del av dess totala arbete, men för en hacker som vill gissa lösenord kan det göra att arbetet tar tusenfaldigt längre tid. Det är det workfactorn eller antalet omgångar representerar i crypt, och vad Sony? gör när han loopar funktionen.

Skickades från m.sweclockers.com

Visa signatur

Abstractions all the way down.

Permalänk
Avstängd

Är det här ett bra sätt att kryptera på? Vad kan bli bättre?
Det är nästan identiskt med vad Tunnelsork skickad.

function get_salt($length){ $salt = ''; $chars = './ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvxyz0123456789'; for($i = 0;$i < $length; $i++){ $salt .= $chars[rand(0,(strlen($chars)-1))]; } return $salt; } function has_text($salt, $password){ $crypt_password = crypt($password,sprintf('$2a$%\'02d$%s$',10,$salt)); return $crypt_password; } $pass = 'pass1234'; $new_salt = get_salt(60); $hash_text = has_text($new_salt,$pass);

Permalänk
Legendarisk

Varför har du gjort saltet längre än manualen säger att det ska vara?

Skickades från m.sweclockers.com

Visa signatur

Abstractions all the way down.

Permalänk
Avstängd

Det tänkte jag inte ens på. Har det någon betydelse?