TheProgrammer Posted December 3, 2006 Share Posted December 3, 2006 Hello people, I've been working with php for a long time, many times with quite advanced stuff but never needed, got the chance or the time to implement a more complex and secure authentification method for a site's private section for example. What i used until now was something like this (the main ideea not the actual implementation):- i kept the username and the password in a mysql database (the password hashed)- i verified the authentification like this (some parts are not real code, only the ideea, but that's what i'm looking for, the main ideea)[code]$auth = false;if( isset( $_POST['username']) && isset($_POST['password']) ){ $u = [i]get_user_from_database[/i] $p = [i]get_password_from_database[/i] if( $u == htmlentities(trim($_POST['username'])) && $p == MD5(MD5(MD5(htmlentities(trim($_POST['password'])))))) { $auth = true; $_SESSION['mysite_username'] = $u; $_SESSION['mysite_password'] = $p; }}else if( isset( $_SESSION['mysite_username']) && isset($_SESSION['mysite_password']) ){ if( $u == $_SESSION['mysite_username'] && $p == $_SESSION['mysite_username'] ) $auth = true;}if($auth){ //the page content}[/code]Well I know it's quite primitive, and the fact that i save the password in session (even hashed), is at least fishy, but never needed something more secure until now.So..can you give me a pice of advice? Or some links? Or anything that can help. You can hit me with some more advanced stuff too. I will understand :). The documentation or samples I found on net ar quite simillar or even worse :)Thank you very much! Quote Link to comment Share on other sites More sharing options...
the_oliver Posted December 3, 2006 Share Posted December 3, 2006 The way i do it is whenever a user logs in, there ip address and session number (as its unique each time) are recorded against there user name in an mysql table. Then whenever they try to access a 'private area' i run a function that checks there current ip address and session number against the one in the table. It does this by checking what these should be for the user_name specified. If they mach there aloud in, if not then they are redirected. (i do this by having the function return a 'true' or 'false' value). The table in the database is refreshed everytime they log in.Code for this is very simple. The only problem i see with this is having to store your database details in a standard file.Hope this makes sence. Shout if not! Quote Link to comment Share on other sites More sharing options...
TheProgrammer Posted December 3, 2006 Author Share Posted December 3, 2006 well, i understand your method but..what do you do with users with the same ip? for example, if i woudnd pay an aditional fee, my network provided woldnt give me a real ip adress, but a private one (10.x.x.x or 192.128.x.x), so me and probably 100 guys would have the gateways ip for someone outside our network. What happens if they acces the page about the same time. We would all be authentificated with only one of us entering the password. Quote Link to comment Share on other sites More sharing options...
the_oliver Posted December 3, 2006 Share Posted December 3, 2006 thats the resion for using the session number as well. The session number is unique to every web broser, and will change every time you close it and open it again. There for you can have as many people as you like on one IP address (as this will genuraly be the outside one), but the session number will always be diffrent. Give me a sec and ill see if i can find my code to post. Quote Link to comment Share on other sites More sharing options...
TheProgrammer Posted December 3, 2006 Author Share Posted December 3, 2006 i see.. thanks! :D. quite simply and effective also. no need to bother with the code. i'm sure that i can do it once i have the algorithm Quote Link to comment Share on other sites More sharing options...
the_oliver Posted December 3, 2006 Share Posted December 3, 2006 ok, have posted the 'check' code i use below. Try this first though.[code]<?phpsession_start();echo session_id();?>[/code]If you run the script. Quit your browser and run it again you will see that the number changes every time you do this. The code below criticaly requires the ip address AND session id to be the same. The ip address is not realy very important i just like to know where my users are![code]function check_client_cridentials($uid){global $pg_connection;session_start();$ip=$_SERVER['REMOTE_ADDR'];$query = "SELECT ip_address,session_id FROM authenticated_users_credentials WHERE user_id = '".$uid."'";$result = pg_query($pg_connection, $query);$data = pg_fetch_array($result); //CHECK IP ADDRESS if ( $data["ip_address"] == $ip ) { $test1 = 1; } else { $test1 = 0; } //IF FIRST TEST IS PASSED CHECK AGAINST SESSION if ( $data["session_id"] == session_id() ) { $test2 = 1; } else { $test2 = 0; } //RETURN WETHER CRIDENTIALS CHECKED OUT OR NOT if ( $test1+$test2 == 2 ) { return "pass"; } else { return "fail"; }}if ( check_client_cridentials('13') == 'pass' ){ //CRIDDENTIALS CHECK OUT, LET THEM INTO PRIVATE AREA echo "Bingo";}else{//CRIDDENTIALS FAILD, DO NOT ALLOW INTO PRIVAT AREAecho "nhaaa";}[/code]Hope this helps. Sorry its two posts! Quote Link to comment Share on other sites More sharing options...
TheProgrammer Posted December 3, 2006 Author Share Posted December 3, 2006 thank you very much! ;) Quote Link to comment Share on other sites More sharing options...
lukevanin Posted December 4, 2006 Share Posted December 4, 2006 TheProgrammer: I think the main issue, as you mentioned, is that you're obtaining security through obscurity. Although this is the done thing by some major companies <cough>microsoft</cough> it's main weakness is that the system is only secure as long as the sensitive information stays hidden (like the username in your examples). So, the goal is to somehow use information that stays secure even if it is found.One easy method to make your logins secure, is to store the identity of the user not with a username/password, but with some other value that uniquely relates to their login, but without revealing their identity. For example, after a user has logged in you would generate a cookie with a unique serial number (probably an MD5 hash based on the time). You would store this in your database, and next time the user initiates a request you read the hash back from the value stored in the cookie. If the value from the client's cookie matches the value in your database, you know the user was authenticated and the action is allowed. Then, you mark this hash as having been used and issues a new hash which overwrites the client's cookie and is stored for the next transaction. The point is that each hash can only be used once. If a hacker steals a hash, they only get to run the action that the user would have run anyway, but the user's password is never revealed. Of course you could also store this hash in a session instead.The other thing to consider is the actual mechanism used to transfer the user's authentication data from the browser to your server. The HTTP protocol supports two different authentication mechanisms, which are described in RFC-2617 http://www.ietf.org/rfc/rfc2617.txtBy using the built in mechanisms, you can effectively bypass the need for sessions or cookies, and even avoid sending the username or password over the network. Perhaps the best place to start with this by reading the "HTTP authentication with PHP" chapter in the PHP documentation [url=http://www.php.net/manual/en/features.http-auth.php]http://www.php.net/manual/en/features.http-auth.php[/url]Here is a sample code fragment for handling the basics of authentication. Note, this script is not complete as it does not include the mechanics for a database connection or error handling.[code]/** * @author Luke Van In 2006 * * @class auth Class for providing HTTP compliant user authentication * */ class auth{ var $authenticated; var $auth; // function authenticate() { // deny access if no username/password was entered if ( (!$_SERVER['PHP_AUTH_USER']) || (!$_SERVER['PHP_AUTH_PW']) ) { $this->deny($p); return false; } // query the database for a record matching the entered username and password $sql = " SELECT * FROM auth WHERE username = '" . mysql_escape_string($_SERVER['PHP_AUTH_USER']) . "' AND password = '" . mysql_escape_string($_SERVER['PHP_AUTH_PW']) . "' LIMIT 0,1 "; $r = mysql_query($sql); $result = mysql_fetch_assoc($r); // allow access if matching username / password was found if (count($result) == 1) { $this->allow($result[0]); return true; } // othrwise deny access $this->deny(); return false; } // function unauthenticate() { $this->deny(); } // function allow($auth) { $this->authenticated = true; $this->auth = $auth; print('Authentication successful. ' . print_r($auth, true)); } // function deny() { // popup a login prompt in the browser's window header('WWW-Authenticate: Basic realm="My Realm"'); header("HTTP/1.0 401 Unauthorized"); $this->http_response(HTTP_ERROR_UNAUTHORIZED); // print('Authentication denied. ' . print_r($auth, true)); } }?>[/code]And an example usage of the class:[code]$auth = new auth();$auth->authenticate();if ($auth->authenticated)print("signed in :)");elseprint("authentication failed :(");[/code]... and to provide a "Sign Out" feature:[code]$auth = new auth();$auth->unauthenticate();[/code]The RFC goes even further to provide a more secure form of authentication over HTTP using a digest string, which circumvents the need to transfer the username or password over the network. Adding SSL on top of HTTP digest authentication would provide a very secure authentication mechanism. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.