views:

170

answers:

5

I have just started PHP and mySQL and need to know if this is "safe". The login information is passed into the following PHP file through AJAX (jQuery).

jQuery AJAX

$("#login_form").submit(function(){
    $.post("login.php",{user:$('#username').val(),pass:$('#password').val()} ,function(data)

PHP

ob_start();
mysql_connect("-", "-", "-") or die("ERROR. Could not connect to Database."); 
mysql_select_db("-")or die("ERROR. Could not select Database.");

//Get Username and Password, md5 the password then protect from injection.

$pass = md5($pass);
$user = stripslashes($user);
$pass = stripslashes($pass);
$user = mysql_real_escape_string($user);
$pass = mysql_real_escape_string($pass);

//See if the Username exists.
$user_result=mysql_query("SELECT * FROM users WHERE username='$user'");
$user_count=mysql_num_rows($user_result);

if($user_count==1){
    if($pass_length==0){ echo "userVALID"; }
    else{       
        $pass_result=mysql_query("SELECT * FROM users WHERE username='$user' and password='$pass'");
        $pass_count=mysql_num_rows($pass_result);       
        if($pass_count==1){             
            session_register("user");
            session_register("pass"); 
            echo "passVALID";
        }
        else { echo "passERROR"; }      
    }
}
else { echo "userERROR"; }

ob_end_flush();

I know this may not be the best way to do things but, it is the way I know! I just want to know if it has any major security flaws. It is more of a concept for me and therefore I am not incorporating SSL.

+5  A: 

It suffers from

  • Sending the password over an unencrypted connection (use HTTPS at least to send the username and password; this protects the password against passive attackers but not against active ones. To be secure against active attackers, you must encrypt all the communications).
  • Storing the password in the database (you should store a salted hash instead).
Artefacto
This is more of a recreational project as it is my school holidays! As it is just a project I am not willing to pay for a SSL certificate unless I actually apply this with a genuine use. Thanks for the Salted hash suggestion!
Phil
@Phil Well, strictly speaking you don't need SSL to do a secure authentication, you can use a variant of [digest authentication](http://en.wikipedia.org/wiki/Digest_authentication). But in this case, I believe you can't store a salted hash (well, you can, but if the database data is exposed, the attacker will be able to login as any user anyway).
Artefacto
@Atrefacto ... actually `$pass = md5($pass);` (Line 7). I believe he's storing the MD5 hash -- not very secure, but it *isn't* plaintext.
Sean Vieira
@Sean You're right. He didn't add salt, though.
Artefacto
Salting = Done.
Phil
+4  A: 

Also never tell user things like "user doesn't exist" or "incorrect password". It's much better if you just print out "Incorrect username or password" so everyone cannot check for existing usernames and then try to guess password for these.

Māris Kiseļovs
I am aware of this issue but as this was a project that I am using to learn about PHP and mySQL I thought it would be a bit more interesting to incorporate some more functions. The jQuery actually pulls the returned data from the PHP file and changes the css based on that. So when the username input is blurred the background turns green. I have not applied this to the password though for obvious reasons! Thanks!
Phil
I personally dislike that option. Then I don't know if I got the username or the password wrong. Rate-limit the attempts for each username if you're concerned about this.
Artefacto
Goes red if the username is wrong. That's how you know.
Phil
That doesn't make sense. There are plenty of sites that have a full member list so being able to know what user names exist is not a security problem.
Lotus Notes
A: 

Are you sure you mean to do stripslashes and not addslashes?

Calle
No, i think he's moslty right. you shouldn't do an addslahses() and then a mysal_real_escape_string().
Rook
Alright, I was just trying to raise awareness around the fact that stripslashes on a string that's md5 will do nothing, and I'm not sure it will do any use to do it on the username since he's doing a mysql_real_escape_string after that... but it's good that you clarified that he didn't need addslashes because I wasn't sure about that.
Calle
+3  A: 

You should make this change just in case people have a backslash in their password:

if(get_magic_quotes_gpc()){
   $user = stripslashes($user);
   $pass = stripslashes($pass);
}
$user = mysql_real_escape_string($user);
$pass = sha256($salt.$pass);

First and foremost md5 is very bad. Also md5() and mysql_real_escape_string() is redundant. Collisions have been generated in the wild. sha1() although weakened is still much more secure and no collisions have been generated (yet). The best choice would be sha256 in php, or using the mhash library.

$pass = md5($pass);

You also need to salt the password.

Rook
Thanks for the info; I know that I need to change it to SHA however on my first attempt this did not work. I had not heard of salting so thanks again for the info!
Phil
Now I feel stupid. The VARCHAR in my database was limited to 50 so when SHA1'd it cut some of it off... Sorted now, thanks.
Phil
@Phil no worries. I like the "text" datatype, but hashes will always be the same size so a varchar is probably better anyway.
Rook
Ahh Salting is much easier than I though. Imma geek 'cause it turns out I am enjoying this stuff. I saw that mysql_real_escape_string() prevents SQL injection. So what would I use instead?
Phil
+1  A: 

session_register() is deprecated, you should be using $_SESSION[].

You're also performing your string escapes on a hashed password string $pass; it will always have a hex value and so doesn't need to be escaped. You can perform escapes on the password string before the hash, but that's only marginally useful (e.g., if you allowed passphrases to be saved by users that included characters that needed to be escaped. Generally I disallow this on the registration side of the code). You should also use a salt.

godheadatomic