Page 1 of 1

Professional Level Login Design [Pt. 1] How to design a secure, professional level login scheme. Rate Topic: ****- 2 Votes

#1 joeyadms  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 41
  • View blog
  • Posts: 178
  • Joined: 04-May 08

Posted 14 June 2008 - 05:55 AM

*
POPULAR

Creating a Secure, Professional Login Module

Intro
Logins are one of the first things people want to learn, however seldom do they expand on it.
Authentication mechanisms should be very well protected, you are only as strong as your weakest link.

A lot more things go into authentication than just comparing strings. Ideally you should be implementing
each of the following in your login scheme.

- Safe Errors
- Injection Protection
- Encryption
- Correct Permissions
- Safe Data Stores
- IP Locking
- User Locking
- Conditional CAPTCHA
- Forgot Pass
- Connection

I'll Go over each of them next.

Safe Errors
This is usually the culprit of newer developers, or devs who are
trying to keep things professional but go too far for security's sake.

If a user attempts to login and there username matches a record but the password
does not, you do not want to give an error saying the password is wrong. Your errors for all
failed login attempts should be EXACTLY the same. This prevents people/scripts from enumerating
users on your site. The best way is to have a configuration, and set a variable for the error string.

Injection Protection
SQL injection, I'll say it a million times is the most dangerous vulnerability out there.
Using an injection, an attacker can login as any user, or the top user in the returned recordset, or even
compromise your server alltogether. Always use the escape function for your DBMS , such as mysql_real_escape string
for mysql. Use this on EVERY variable that goes into your querys, no matter what medium they came from.

Encryption
Never, Never,Never store sensitive data in your database without encryption. There is a rule for encryption.
Will you ever need to retrieve the data in plaintext, such as credit card #'s, ss#'s, etcs
If so then you need to use an encryption scheme, try using AES first, Tripple DES (3DES) second, both
can be implemented using php's mcrypt() function.

If you only need a string for comparison, and do not need retrieval, such as passwords (Note: even using forgot
password functions, you never need to retrieve original pass, you should always make user generate a new one), you
will want to use a Hashing function. Hashing is a one-way encryption that cannot be decrypted, only bruteforced.

For hashing you will want to use SHA512/SHA1 first and md5 last. These can be done with the following functions
hash() sha1() md5()

Also you will need to specify a Key, or Salt. Always do the longest key possible if using a key. A salt is a
word that is added to the plaintext before encryption. This can be any word you want, just concatenate it onto
the plaintext before encryption. Don't forget to use it again when comparing hashes, or decrypting encryptions.

A salt protects you if an attacker is able to get the hashes from your database, then it would be very difficult for him
to brrute force without it.

Correct Permissions
This is very common for people to forget file system protection. Due to php being interpreted, not compiled, if someone gained control of your server where your files are hosted, they would have access to your php files, so
all that hashing, those keys/salts can be retrieved, and even code could be altered to log data in plaintext format.

Moral of this story is make sure your files are behind web root if possible, and make sure folders have correct file system permissions.

Safe Data Stores
Don't use flat files for storing sensitive information. Nor should you be passing around user's sensitive data in cookies. Use a database management system such as MYSQL, and use Sessions for user info, but never store passwords or sensitive data in a persistent state like sessions , only keep those in one place, your guarded database.

IP Locking
Whenever a certain IP attempts to login and fails too many times, say more than 3-10 depending on how sensitive info your site contains 3 being a bank 10 being a forum, you want to lock that IP from logging in for a while. The length, again, depends on your situation, say an 30minutes - hour for a forum to a day for a bank.

User Locking
If someone attempts to login as a user and fails a number of times, no matter from what IP, you should lock that username for a period of time. Use the above template as a guide for user locking as well.

Conditional CAPTCHA
It is very annoying to have to enter a CAPTCHA for everything all the time. And the more difficult we make them for OCR engines to decrypt the harder it is for people to get them right. Here is my solution.

If a user or ip attempts to login and fails more than twice, you should have them enter a CAPTCHA to insure they are human. This way, coupled with the locking above, you can make the CAPTCHA nice and easy to read.

Forgot Password
If a user forgets their password, never give them the exact password back, if you are following my guidelines that should be impossible anyway, have them create a new one.

Also, just don't send a request to their email. Require them to enter details to have it sent, like birth day, secret question etc.

Any failed attempts? Then follow the locking standard above.

You also want to log the IP from which the request was made, and send a confirmation to the user's email saying someone tried to request a password.

Connection
If possible, get a certificate, and use HTTPS for logins, this can help prevent sniffing, and man in the middle attacks, although will not stop them altogether, but it is much much safer. This is not required, but if it is possible is nice to use.


Creating the Module
Now you didn't think I would leave you hanging. Lets go through and create an OO interface for authentication.

Start off by making your class
class userAuth {

}



Now lets add our error string definition
class userAuth{
	private $login_error_message = 'Login Failed.';

}



Lets add our escape wrapper
class userAuth{
	private $login_error_message = 'Login Failed.';
	
	
	public function escape($var){
		// Assumes mysql connection
		// Change if necessary
		if(is_array($var){
			foreach($var as $key=>$val){
				$return[$key] = mysql_real_escape_string($val);
			}
		} else {
			$return = mysql_real_escape_string($var);
		}
		return $return;
	}

}



Now our hashing, encrpytion functions. When creating our encryption functions, we must return values as base64 encoded, this way all the NPC (non printable characters) are not compromised. In the encrypt function
we return encrypted and encoded string, in our decrypt function first we decode the string then attempt to decode it.

These functions are for encrypting/decrypting with AES, and hashing with SHA512, using $this->_salt for a key.
class userAuth{
	private $login_error_message = 'Login Failed.';
	private $_salt = 'This is my salt';

function encrypt($var){	   
	$td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', 'ecb', ''); 
	$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); 
	mcrypt_generic_init($td, $this->_salt, $iv); 
	$encrypted_data = mcrypt_generic($td, $var); 
	mcrypt_generic_deinit($td); 
	mcrypt_module_close($td); 
	$encoded_64=base64_encode($encrypted_data); 
	return $encoded_64; 
}	


function decrypt($encoded_64){ 
	$decoded_64=base64_decode($encoded_64); 
	$td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', 'ecb', ''); 
	$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); 
	mcrypt_generic_init($td, $this->_salt, $iv); 
	$decrypted_data = mdecrypt_generic($td, $decoded_64); 
	mcrypt_generic_deinit($td); 
	mcrypt_module_close($td); 
	return $decrypted_data; 
} 
	public function hash($var){
		$var = $this->_salt . $var;
		return hash('sha512',$var);
	}
	
	
	public function escape($var){
		// Assumes mysql connection
		// Change if necessary
		if(is_array($var)){
			foreach($var as $key=>$val){
				$return[$key] = mysql_real_escape_string($val);
			}
		} else {
			$return = mysql_real_escape_string($var);
		}
		return $return;
	}

}




This completes Part1, next time we will continue with our blocking and
CAPTCHA system. Stay Syndicated for more info!

If you are unable to read this fluently, or extend this, or are confused, you need to read up on some tutorials on here and good on Object Oriented Programming.

Also some of these function require other libraries, depending
on your version of php, see the following.
http://www.php.net/mcrypt
http://www.php.net/hash

Is This A Good Question/Topic? 7
  • +

Replies To: Professional Level Login Design [Pt. 1]

#2 glenwheeler  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 12-February 09

Posted 12 February 2009 - 08:42 AM

Hi Joey,

This is helping me a great deal, thanks for this. Is it ok to add you by AIM dude?
Was This Post Helpful? 0
  • +
  • -

#3 hadi_php  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 10
  • View blog
  • Posts: 382
  • Joined: 23-August 08

Posted 31 March 2009 - 08:30 AM

 class userAuth{
	private $login_error_message = 'Login Failed.';
	private $_salt = 'This is my salt';

function encrypt($var){	   
	$td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', 'ecb', ''); 
	$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); 
	mcrypt_generic_init($td, $this->_salt, $iv); 
	$encrypted_data = mcrypt_generic($td, $var); 
	mcrypt_generic_deinit($td); 
	mcrypt_module_close($td); 
	$encoded_64=base64_encode($encrypted_data); 
	return $encoded_64; 
}	


function decrypt($encoded_64){ 
	$decoded_64=base64_decode($encoded_64); 
	$td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', 'ecb', ''); 
	$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND); 
	mcrypt_generic_init($td, $this->_salt, $iv); 
	$decrypted_data = mdecrypt_generic($td, $decoded_64); 
	mcrypt_generic_deinit($td); 
	mcrypt_module_close($td); 
	return $decrypted_data; 
} 
	public function hash($var){
		$var = $this->_salt . $var;
		return hash('sha512',$var);
	}
	
	
	public function escape($var){
		// Assumes mysql connection
		// Change if necessary
		if(is_array($var)){
			foreach($var as $key=>$val){
				$return[$key] = mysql_real_escape_string($val);
			}
		} else {
			$return = mysql_real_escape_string($var);
		}
		return $return;
	}

}


nice man....i m begainner i donnt know where to add this codes....

such as - i have login.php conn.php then checklogin.php and memberarea.php

where i have to put this code?
Was This Post Helpful? 0
  • +
  • -

#4 Shane Hudson  Icon User is offline

  • D.I.C Technophile
  • member icon

Reputation: 343
  • View blog
  • Posts: 1,286
  • Joined: 06-December 09

Posted 14 April 2011 - 03:56 AM

It is so true that people always learn basic login systems but do not expand upon them. This is a very good tutorial and one that is much needed, I cannot wait to see the finished series.

One thing I do wonder about though is you say you use SHA AND MD5. I used to do this until I spoke to some "security professionals" (who were a tad on the black hat side I do believe) on IRC who said that it is a complete waste of time and does not add any protection. Personally I could not see how it could not add protection, but a few seminars I watched online seemed to agree with them. It is about hashes not being encryptions, and so it does not add protection.

Do you or anyone else know anything about this? I am starting to get confused! Haha

EDIT: Ah, this was written ages ago.. the rest of the series must be out already.

This post has been edited by Shane Hudson: 14 April 2011 - 03:58 AM

Was This Post Helpful? 0
  • +
  • -

#5 GhandiJones  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 54
  • View blog
  • Posts: 174
  • Joined: 17-March 11

Posted 15 April 2011 - 09:15 AM

View PostShane Hudson, on 14 April 2011 - 03:56 AM, said:

It is so true that people always learn basic login systems but do not expand upon them. This is a very good tutorial and one that is much needed, I cannot wait to see the finished series.

One thing I do wonder about though is you say you use SHA AND MD5. I used to do this until I spoke to some "security professionals" (who were a tad on the black hat side I do believe) on IRC who said that it is a complete waste of time and does not add any protection. Personally I could not see how it could not add protection, but a few seminars I watched online seemed to agree with them. It is about hashes not being encryptions, and so it does not add protection.

Do you or anyone else know anything about this? I am starting to get confused! Haha

EDIT: Ah, this was written ages ago.. the rest of the series must be out already.


Not true at all. It definitely adds a layer of protection. It's a deterrent. For example... You have an awesome car, with the best security system in the world. It has all of the bells and whistles. Now... This would scare a low rent thief or a crackhead away from the car. Which is what hashing does. It adds that level of security. What they mean by it is a waste of time, is.. a really good car thief could have that car half a block away in under a minute and a half. Just some food for thought.
Was This Post Helpful? 0
  • +
  • -

#6 menukadevinda  Icon User is offline

  • D.I.C Regular

Reputation: -7
  • View blog
  • Posts: 470
  • Joined: 14-April 11

Posted 06 August 2011 - 08:16 PM

hi all,

i am new to php. i am wondering why don't anybody talk about the sessions because I found that topic in all loging system. is it neccessay or not important to remember it or it is most essential thing?

i think we can do lot with session in logins. becuse if a thief get copy of the url when u loging to the system he can enter ur site any time with out username and password.

what do u all think about this. actually i am new to php...

thanks in advance,
menuka.
Was This Post Helpful? 0
  • +
  • -

#7 menukadevinda  Icon User is offline

  • D.I.C Regular

Reputation: -7
  • View blog
  • Posts: 470
  • Joined: 14-April 11

Posted 09 August 2011 - 08:47 AM

Blocking an IP can cause an entire network to become blocked. Schools, companies, home networks, etc...

There are a number of ways for attackers to swap IP addresses between requests. There is no guarentee that a single attacker will only be using one IP, or indeed one computer. - For example, an attacker could utilize a botnet to attack your site from multiple random computers, all of which belong to innocent victims of Trojan viruses.
Was This Post Helpful? 0
  • +
  • -

#8 menukadevinda  Icon User is offline

  • D.I.C Regular

Reputation: -7
  • View blog
  • Posts: 470
  • Joined: 14-April 11

Posted 09 August 2011 - 09:05 AM

the best alternative is, to lock an account independently from the IP address. That's how it's done in the real world. That might be stupid for the end-user as she/he can't login after an attack, but provides the highest security.

There are two possibilities:
1) Resetting the password and sending a link to unlock the account via email.
2) Blocking any login-attempt for a defined period of time (15 mins or so).

What's best for you depends on your taste.
Was This Post Helpful? 0
  • +
  • -

#9 lionaneesh  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 0
  • View blog
  • Posts: 15
  • Joined: 01-April 10

Posted 06 September 2011 - 11:42 AM

First of all Nice tutorial. Actually i have been into PHP Development from more than 2 years now and we dont get to see OOP in login scripts! That's the best part of this tutorial! keep up the good work! Thanks

This post has been edited by lionaneesh: 06 September 2011 - 11:43 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1