Jump to content

[SOLVED] Login Security


947740

Recommended Posts

I have a quick question about login security using PHP.  I am working on a website where only administrators can login and only with a password.  That makes it much simpler on the administrators, and it makes it easier on me.  (There are only 4 administrators, so there is not a problem with the same passwords)

 

I am concerned with the security of the login.  When someone logs in, I use md5() to encrypt the password and compare it to the passwords in the database.  If it matches, it logs the user in.  It creates a session variable, $_SESSION['login'] = "true".  Every single administration page checks for the $_SESSION['login'] variable.  If it is not == "true", it sends you back to the home page with an error message.

 

Does anyone see any security concerns with the way I have set it up?  If you need to see the code, just ask.  I will probably put it up later, but I do not have it on me.

 

~Thanks

 

Link to comment
Share on other sites

Should be fine, the only issue here is if someone grabs your database, the plain-text password won't be hard to bruteforce (due to rainbow tables).

 

Assuming your SQL code is injection-safe, an attacker will have a hard time getting access :)

Link to comment
Share on other sites

the plain-text password won't be hard to bruteforce (due to rainbow tables)

 

It's not plain text, and good luck trying to find a collision in md5. 

 

As you stated, the real threat is sql injection.

 

The password in the database is encrypted using PHP's md5(),

 

md5 is not an encryption.  It's a hash algorithm.

 

Are there any specific things to stop injection?

 

Use input verification (i.e. make sure a text input only contians text) and use mysql_real_escape_string or PDO and prepared statements.

Link to comment
Share on other sites

It's not plain text, and good luck trying to find a collision in md5. 

 

As you stated, the real threat is sql injection.

 

It's not a collision... it uses what a called 'rainbow tables' -> huge tables of prehashed values with their corresponding plain text strings. Allows you to brute force without the overhead of actually performing the hash.

 

It's very fast, and well-known. Why do you think salting hashes has become such common practice? If it wasn't an issue, dumping the user table with an injection wouldn't be so risky assuming passwords were hashed.

Link to comment
Share on other sites

I know of a couple private-access md5 hash tables that are in the terabyte ranges. They cover all ascii chars up to ~20 characters long. If you had something I wanted and I was less moral, then I could probably get access to them.

 

The thing that worries me is insecure passwords. Dictionary-based tables are publicly available

Link to comment
Share on other sites

The thing that worries me is insecure passwords. Dictionary-based tables are publicly available

 

Exactly...it doesn't matter (for the most part) the hash or encryption if the password is weak to begin with.

 

On a side note, md5 is a 128 bit hash, which means there is 2^128 number of values.  According to the calculator on my Fedora 8 laptop, that comes to ~ 3.4*10^38 combinations.

 

MySQL's largest integer data type is BIGINT, which according to their documentation, and unsigned BIGINT has a max value of 18446744073709551615. 

 

If you divide the first number (2^128) by the second, you get 18446744073709551617.  This means it would take 18,446,744,073,709,551,617 mysql tables, all with a BIGINT primary key, to find every hash possible.

 

Terabytes is still a very small percentage.

Link to comment
Share on other sites

The easiest method is a salt of a predetermined length appended to the hash...

 

This is described here

http://phpsec.org/articles/2005/password-hashing.html

 

But here's the basic idea:

 

<?php

// Multiples of 16 best here to obscure better
define('SALT_LENGTH', 32);
define('SALT_OFFSET', 12);

function salted_md5 ($input, $salt = FALSE) {

 // Make sure constants are defined
 if ( !defined('SALT_LENGTH') || !defined('SALT_OFFSET') )
	return FALSE;

// If no salt is defined, generate one
 if ($salt === FALSE)
	$salt = md5( uniqid('', TRUE) );

// Make sure legth and offset make sense
if ( SALT_LENGTH > strlen($salt) || SALT_OFFSET > strlen($salt) )
	return FALSE;

// Now that we've made sure the length checks out, truncate salt if needed
$salt = substr( $salt, mt_rand(0, strlen($salt) - SALT_LENGTH), SALT_LENGTH );

// Hash input
$hash = md5($input);

// Use offset to mix up salt and hash together
return substr( $salt, 0, SALT_OFFSET ) . $hash . substr( $salt, SALT_OFFSET );

}

function get_salt ($hash) {

 // Make sure constants are defined
 if ( !defined('SALT_LENGTH') || !defined('SALT_OFFSET') )
	return FALSE;

// Extract salt
return substr( $hash, 0, SALT_OFFSET ) . substr( $hash, strlen($hash) - SALT_LENGTH + SALT_OFFSET );

}

// Does it work?

$hash = salted_md5('test');
$salt = get_salt($hash);
$compare = salted_md5('test', $salt);

if ($hash == $compare)
echo 'Match found!';
else
echo 'No match';

// Example usage
$q = 'SELECT `password` FROM `users` WHERE `username` = \'' . mysql_real_escape_string($_POST['username']) . '\' LIMIT 1';
$r = mysql_query($q);

if (mysql_num_rows($r) !== 1)
exit('User not found');

$pass = mysql_result($r, 0);
$salt = get_salt($pass);

if ( salted_md5($_POST['password'], $salt) != $pass )
exit ('Invalid password');

// When adding a new user, just call salted_md5 without second argument to have the salt made for you


?>

 

That's a basic example. Use the hash() function rather than md5 to mix up the length of your hashes and it is theoretically impossible to reverse, even by brute forcing :)

 

Exactly...it doesn't matter (for the most part) the hash or encryption if the password is weak to begin with.

 

The above function protects against weak passwords. As the holder of someone's passwords, you are responsible for their secrecy. In this way, even if your user table gets dumped (heaven forbid), they will not be able to figure out passwords, no matter how weak the password.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.