Brazzan Posted May 30, 2008 Share Posted May 30, 2008 I've seen alot of, what I think, good PHP programmers in this forum. I want you to take a look at this login class and other related classes. Im sorry about the commenting..it's in Swedish. But if you know your PHP you should be fine without them...but I admit, it's always helpful with comments. I could'nt be bothered to translate EDIT: The file settings.php that's included only contains 3 variables. They are just used for some of the error handling and a static salt. demo_register.php <?php if(isset($_POST['login'])) { require_once("system/class/class_login.php"); //Inkluderar klassen login require_once("system/class/class_accountHandler.php"); //Inkluderar klassen handler require_once("system/settings/settings.php"); //Inkluderar inställningarna require_once("db/connect.php"); //Inkluderar anslutningen till databasen $hndl = new accountHandler(); //Anropar klassen accountHandler $auth = new login($_POST['username'], $_POST['password'], $static_salt, $usr_min_length, $pwd_min_length, $conn, $hndl); //Anropar klassen login, samt förser __construct med värden $auth->show_errors(); //Skriver ut errors...optional } ?> <form method="post" action="demo_login.php"> Username<br /> <input type="text" name="username" /><br /> Password<br /> <input type="password" name="password" /><br /> <input type="hidden" name="hidden" value="" /> <input type="submit" name="login" value="Login" /> </form> class_login.php <?php class login { private $static_salt; //Lagrar ett statiskt salt. Detta salt finns i settings.php private $conn; //Lagrar en anslutning till databasen private $generate; //Lagrar en anslutning till klassen accountHandler private $usr_min_length; //Lagrar minsta antalet tecken som användarnamn får ha. Går att ställa in i settings.php private $pwd_min_length; //Lagrar minsta antalet tecken som lösenordet får ha. Går att ställa in i settings.php private $username; //Lagrar användarnamnet från formuläret private $password; //Lagrar lösenordet från formuläret private $db_id; //Lagrar id't från databasen private $db_username; //Lagrar användarnamnet från databasen private $db_password; //Lagrar lösenordet från databasen private $db_salt; //Lagrar saltet från databasen private $db_x; //Lagrar x från databasen private $user_exists; //True om användaren existerar, annars False private $user_length; //True om längden på användarnamnet är acceptabelt, annars False private $password_length; //True om längden på lösenordet är acceptabelt, annars False private $password_match; //True om lösenordet från formuläret(efter behandling) matchar lösenordet från databasen, annars False //Metoden autoladdas så fort klassen körs. Den förser klassen med nädvändig information public function __construct($username, $password, $static_salt, $usr_min_length, $pwd_min_length, $conn, $hndl) { $this->username = $username; //Lagrar användarnamnet från formuläret i klassvariablen username $this->password = $password; //Lagrar lösenordet från formuläret i klassvariablen password $this->static_salt = $static_salt; //Lagrar det statiska saltet från settings.php i klassvariablen static_salt $this->usr_min_length = $usr_min_length; //Lagrar en siffra i klassvariablen $usr_min_length som motsvarar antalet tecken ett användarnamn minst ska ha. Värdet finns i settings.php $this->pwd_min_length = $pwd_min_length; //Lagrar en siffra i klassvariablen $pwd_min_length som motsvarar antalet tecken ett lösenord minst ska ha. Värdet finns i settings.php $this->conn = $conn; //Lagrar anslutningen till databasen i klassvariablen $conn $this->generate = $hndl; //Lagrar en anslutning till kalssen accountHandler i klassvariablen generate $this->check_values(); //Anropar metoden check_values() $this->bake_values(); //Anropar metoden bake_values() $this->set_session(); //Anropar metoden set_sessiob() } /* #### ### ## # */ //Metoden för att kontrollera värden från formuläret private function check_values() { //Räknar om det angivna användarnamnet förekommer 0 gånger, eller 1 gång. $do= $this->conn->prepare ("SELECT COUNT(id) as antal FROM table WHERE username = :user "); $do->bindParam(':user', $this->username, PDO::PARAM_STR); $do->execute(); $obj = $do->fetch(PDO::FETCH_OBJ); $db_count = intval($obj->antal); //Innehåller antalet gånger användarnamnet från formuläret förekommer i databasen if($db_count < 1){ $this->user_exists = false; } //Kontrollerar om användaren inte existerar if($db_count > 0){ $this->user_exists = true; } //Kontrollerar om användare existerar if(strlen($this->username) < $this->usr_min_length) { $this->user_length = false; } //Kontrollerar om längden på användarnamnet inte är acceptabelt if(strlen($this->username) >= $this->usr_min_length) { $this->user_length = true; } //Kontrollerar om längden på användarnamnet acceptabelt if(strlen($this->password) < $this->pwd_min_length) { $this->password_length = false; } //Kontrollerar om längden på lösenordet inte är acceptabelt if(strlen($this->password) >= $this->pwd_min_length) { $this->password_length = true; } //Kontrollerar om längden på lösenordet är acceptabelt //En checkpoint som måste passeras if($this->user_exists == true){ if($this->user_length == true){ if($this->password_length == true){ //Hämtar alla nödvändiga uppgifter från databasen $do2 = $this->conn->prepare ("SELECT id, username, password, salt, x FROM table WHERE username = :user "); $do2->bindParam(':user', $this->username, PDO::PARAM_STR); $do2->execute(); $obj = $do2->fetch(PDO::FETCH_OBJ); $this->db_id = intval($obj->id); //Lagrar kontots id i klassvariablen $db_id $this->db_username = $obj->username; //Lagrar kontots användarnamn i klassvariablen $db_username $this->db_password = $obj->password; //Lagrar kontots lösenord i klassvariablen $db_password $this->db_salt = $obj->salt; //Lagrar kontots salt i klassvariablen $db_salt $this->db_x = intval($obj->x); //Lagrar kontots x i klassvariablen $db_x $conn = null; //Stänger anslutningen till databasen } } } } /* #### ### ## # */ //Metod som tar hand om lösenord, salt och x. Lagrar även allt i databasen private function bake_values() { //Checkpoint som måste passeras if($this->user_exists == true){ if($this->user_length == true){ if($this->password_length == true){ //Här tar vi hjälp av en annan klass som tar hand om lösenordet, saltet, x, samt lagrar det i databasen $baked_pass = $this->generate->system_password($this->password, $this->static_salt, $this->db_salt, $this->db_x); if($baked_pass == $this->db_password) { $this->password_match = true; } //Kontrollerar om lösenordet från formuläret (efter behandling) matchar lösenordet från databasen if($baked_pass !== $this->db_password){ $this->password_match = false; } //Kontrollerar om lösenordet från formuläret (efter behandling) inte matchar lösenordet från databasen } } } } /* #### ### ## # */ //Metod som skriver ut error-meddelande public function show_errors() { if($this->password_match == false){ $error = "Användarnamn eller lösenord felaktigt!"; } //Om lösenorden inte matchar if($this->user_length == false){ $error = "Användarnamn eller lösenord felaktigt!"; } //Om längden på användarnamnet inte är acceptabelt if($this->password_length == false){ $error = "Användarnamn eller lösenord felaktigt!"; } //Om längden på lösenordet inte är acceptabelt if($this->user_exists == false){ $error = "Användarnamn eller lösenord felaktigt!"; } //Om användaren existerar echo $error; //Skriver ut meddelandet } /* #### ### ## # */ //Metod som skapar sessionen private function set_session() { if($this->password_match == true){ if($this->user_length == true){ if($this->password_length == true){ if($this->user_exists == true){ session_start(); $PROT = sha1(mt_rand($this->db_x, 100)); $_SESSION['accID'] = $this->db_id; $_SESSION['accUSER'] = htmlspecialchars($this->db_username); $_SESSION['accPROT'] = $PROT; $_SESSION['accSEC'] = sha1($_SESSION['accPROT'] . $_SESSION['accID'] . $_SESSION['accUSER'] . strlen($_SESSION['accUSER'])); } } } } } } //Avslutar klassen ?> class_accountHandler.php <?php class accountHandler { //Metod som tar hand om "skapa konto" processen public function new_system_account($username, $password, $email, $static_salt, $date, $conn) { $db_x = mt_rand(2, 20); //Genererar ett slumpat tal mellan 2 och 20. Detta tal används för att bestämma hur många gånger salt-loopen ska köras. $signs = "abcdefghijklmnopqrstuvxyz 1234567890!@#£%&=?+-"; //Ur denna variablen hämtas alla tecken för det slumpade saltet $length = strlen($signs); //innehåller värdet på antalet tecken som finns i $signs //Skapar ett slumpat salt for($i=0; $i<$db_x; $i++) { $rand = mt_rand(0, $length); $salt .= substr($signs, $rand, 1); } $db_salt = sha1($salt.md5($db_x)); //Innehåller det färdiga saltet (dynamiskt) $db_pass = $this->system_password($password, $static_salt, $db_salt, $db_x); //Anropar metoden system_password för att behandla lösenordet //Sparar kontot i databasen $do = $conn->prepare("INSERT INTO table (username, password, salt, x, email, date) VALUES (:user, :pass, :salt, :x, :email, :date)"); $do->bindParam(':user', $username, PDO::PARAM_STR); $do->bindParam(':pass', $db_pass, PDO::PARAM_STR); $do->bindParam(':email', $email, PDO::PARAM_STR); $do->bindParam(':salt', $db_salt, PDO::PARAM_STR); $do->bindParam(':x', $db_x, PDO::PARAM_INT); $do->bindParam(':date', $date, PDO::PARAM_STR); $do->execute(); $conn = null; //Stänger anslutningen till databasen. } /* #### ### ## # */ //Metod som behandlar lösenord från formulär public function system_password($password, $static_salt, $db_salt, $db_x) { $password = md5($password); //Hashar lösenordet med md5 //Loop-behandlar lösenordet for($i=0; $i < $db_x; $i++) { $password = md5($static_salt.sha1($password).$db_salt.md5($db_x)); } $baked_pass = sha1($password); //Färdigt lösenord return $baked_pass; } } ?> connect.php <?php $hostname = 'address'; // Adress till databasen $username = '****'; //Användarnamn för databasen $password = '****'; //Lösenord för databasen $database = '****'; //Namnet på databasen //Låt denna variabel vara som den är. Används för att införa datum och tid i databasen $date = date("Y-m-d"); //Följande skapar själva anslutningen till database try { $conn = new PDO("mysql:host=$hostname;dbname=$database", $username, $password); } catch(PDOException $e) { echo $e->getMessage(); } ?> Link to comment Share on other sites More sharing options...
kbh43dz_u Posted May 31, 2008 Share Posted May 31, 2008 english comments would have be fine for better understanding Unless your code is not vulnerable against sql-injections I didn't find security problems. You are using SHA-1 which is broken, but still should be more secure than MD5 (also broken) - so just for information purpose. Keep it in your head, you could use mcrypt functions if available on your server. (...but maybe someone else will find a security issue) kind regards! Link to comment Share on other sites More sharing options...
Brazzan Posted May 31, 2008 Author Share Posted May 31, 2008 english comments would have be fine for better understanding Unless your code is not vulnerable against sql-injections I didn't find security problems. You are using SHA-1 which is broken, but still should be more secure than MD5 (also broken) - so just for information purpose. Keep it in your head, you could use mcrypt functions if available on your server. (...but maybe someone else will find a security issue) kind regards! PDO takes care of the SQL-injections. By broken I guess you meen one-way..in other words hash. In my case... the only way to re-create a password that's stored in the database is by bruteforce...or if you want to build a rainbow-table for each pass and take the random salt in consideration. Link to comment Share on other sites More sharing options...
kbh43dz_u Posted May 31, 2008 Share Posted May 31, 2008 no, by broken I don't mean one way. by broken I mean that it is not secure for 100% anymore. it IS possible (possible but still hard and complex) to calculate/figure out passwords which have the same hash. (I'm not saying that your application would need more security, but still it is not perfect - *paranoid* ) Link to comment Share on other sites More sharing options...
Brazzan Posted May 31, 2008 Author Share Posted May 31, 2008 no, by broken I don't mean one way. by broken I mean that it is not secure for 100% anymore. it IS possible (possible but still hard and complex) to calculate/figure out passwords which have the same hash. (I'm not saying that your application would need more security, but still it is not perfect - *paranoid* ) The way I figure it... if they (by they I meen hackes) has gained access to the DB....they probably have rooted the server too. I consider my security the last defence and a way to give me time to make the DB they have useless.... useless on my site that is. And by the way.... nothing is 100% secure, it never has been and never will be. Your system may be perfect, but still... the greatest threat is sabotage by employee. So... always tell the staff how mutch you love them before you go to bed Link to comment Share on other sites More sharing options...
kbh43dz_u Posted May 31, 2008 Share Posted May 31, 2008 when I talk about 100% secure I'm talking about an algorithm that isn't hackable - by now. It is possible that maybe someone finds a way to hack it, but at the time it is not possible. And when I talk about "not 100% secure" i mean that it was hacked already. (there could be many ways to get data from your database...) But I'm just informing you -it's up to you what you do with my posts.) kind regards. Link to comment Share on other sites More sharing options...
Brazzan Posted May 31, 2008 Author Share Posted May 31, 2008 when I talk about 100% secure I'm talking about an algorithm that isn't hackable - by now. It is possible that maybe someone finds a way to hack it, but at the time it is not possible. And when I talk about "not 100% secure" i mean that it was hacked already. (there could be many ways to get data from your database...) But I'm just informing you -it's up to you what you do with my posts.) kind regards. I appreciate your comments...especially since you're the only one who has shown interrest The thing is.. I like being critizized and receiving comments..good or bad. It makes me think and in the end.. it makes me a better programmer. I dont always agree, but I always respect good comments. Link to comment Share on other sites More sharing options...
darkfreaks Posted August 30, 2008 Share Posted August 30, 2008 class_login.php Warning: Invalid path to PHP binary in config file: /opt/lampp/bin/php Syntax error line: 4 accounthandler.php Warning: Invalid path to PHP binary in config file: /opt/lampp/bin/php Syntax error line: 11 connect.php Warning: Invalid path to PHP binary in config file: /opt/lampp/bin/php Syntax error line: 12 Link to comment Share on other sites More sharing options...
Recommended Posts