Forums: A "secure" Login Script - Forums

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

A "secure" Login Script done in php & mysql

#1 User is offline   Gotisch 

  • Corporal
  • Icon
  • Group: Members
  • Posts: 162
  • Joined: 26-September 03

Posted 11 October 2004 - 12:56 PM

Some time ago someone asked me how he could write a secure login script for his homepage. Of course you can make a script 100% secure but you can make it resonably secure, which is enough for the you-and-me-homepage.

The aim was to write a script where you provide your username and password. And with a successfull login the $_SESSION var 'login' would be set. There was also the problem of bruteforce cracking which was taken care of by only allowing one try every 30 seconds and after 3 trys banning the ip for half an hour.

For that script i used PHP and mysql.

you can see the code at work here: http://bwl.cositel.com/login.php

the right username/password is: username/passwort



for the aboce script to work you need mysql.class.php (just rename the txt)

Attached File  mysql.class.txt (3.4K)
Number of downloads: 165

<?
/* login.php - a hopefully "secure" login Script

Mysql tables we need :

1. ipdatenbank :
CREATE TABLE `ipdatenbank` (
`ip` VARCHAR( 15 ) NOT NULL ,
`count` TINYINT( 1 ) NOT NULL ,
`time` INT( 10 ) NOT NULL
);

2. benutzer :
CREATE TABLE `benutzer` (
`username` VARCHAR( 255 ) NOT NULL ,
`passwort` VARCHAR( 255 ) NOT NULL
);

255 is very high.

by Gotisch :)
*/
function check_ip($ip) {
 global $DB;
$ip = mysql_escape_string($ip);
 $ipcheck = $DB->query("SELECT count, time FROM `ipdatenbank` WHERE `ip`='$ip'");
 if (mysql_num_rows($ipcheck) == 0)
 {
$upd = $DB->query("INSERT INTO `ipdatenbank` (count, time, ip) VALUES ('1', UNIX_TIMESTAMP(), '$ip')");
        return 0;
 }
 $array = mysql_fetch_array($ipcheck);
 if ($array['count'] > 3)
 {
        if ($array['time'] + 1800 < time())
        {
         $upd = $DB->query("UPDATE `ipdatenbank` SET `count`='1', `time`=UNIX_TIMESTAMP() WHERE `ip`='$ip'");
         return 0;
        }
        return "You have been blocked for 30 min.";
 }
 if ($array['time'] + 30 < time())
 {
         $upd =  $DB->query("UPDATE `ipdatenbank` SET `count`=count+1, `time`=UNIX_TIMESTAMP() WHERE `ip`='$ip'");
        return 0;
 }
 return "You have to wait 30sec.";
}

function check_user($username, $passwort) {
 global $DB;
 $username = mysql_escape_string($username);
 $usercheck = $DB->query("SELECT passwort FROM `benutzer` WHERE `username`='$username'");
 if (mysql_num_rows($usercheck) != '0')
 {
  $array = mysql_fetch_array($usercheck);
        if ($array['passwort'] == $passwort)
        {
                return 0;
        }
 }
 return "This Username/Password is not OK.";
}
/* username and pass where given.*/
$login = "Please Enter your Username and Password";
if ($_POST['username'] && $_POST['passwort'])
{
 //connect to database.
 require("mysql.class.php");
 $DB=new FM_SQL_CLASS;
 $DB->server="localhost";
 $DB->dbname="yourdb";
 $DB->username="yourusername";
 $DB->password="yourpass";
 $DB->connect();
 $login = check_ip($_SERVER['REMOTE_ADDR']);
 if ($login == '0')
 {
  $login = check_user($_POST['username'], $_POST['passwort']);
  if ($login == '0')
  {
  $_SESSION['login'] = true;
  $login = "You are now Logged in";
  }
 }
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title><? echo $login; ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<?
if($_SESSION['login'])
{
 echo "You are now loggin in and login is set to true;)";
} else {
echo $login; ?>
<br />
<form name="form1" id="form1" method="post" action="<? echo $_SERVER['PHP_SELF']; ?>">
  <input type="text" name="username" />
  <input type="password" name="passwort" />
  <input type="submit" name="Submit" value="Einloggen" />
</form>
<?
}
?>
</body>
</html>


Any suggestions bugs / comments are highly welcome.
0

#2 User is offline   Vixen 

  • Private First Class
  • Icon
  • Group: Members
  • Posts: 25
  • Joined: 03-October 04

Posted 11 October 2004 - 10:27 PM

Shouldn't I use htmlentities and addslashes on the variables to prevent SQL injection/XSS attacks? Or what else do they use for that?
0

#3 User is offline   FuzZyBeeR 

  • Sergeant
  • Icon
  • Group: Members
  • Posts: 246
  • Joined: 18-February 04

Posted 12 October 2004 - 12:30 AM

the mysql_escape_string is used for this.

for more info look at http://www.php.net/mysql_escape_string
0

#4 User is offline   realmasterX 

  • Private First Class
  • Icon
  • Group: Members
  • Posts: 111
  • Joined: 01-December 03

Posted 27 June 2005 - 09:28 AM

You have to reset the 'count'-entery (or delete the db-entery for the IP) if the login is correct! Otherwise you can login 3 times and then you have to wait for half an hour!!!

btw: 'mysql_escape_string' is not up to date! have al look: mysql-real-escape-string

very nice work!
back again.
0

#5 User is offline   myth 

  • Master Sergeant
  • Icon
  • Group: Members
  • Posts: 408
  • Joined: 09-January 04

Posted 27 June 2005 - 05:21 PM

Cheers for the script Gotisch, got a mate that needs to see how to write secure logins, he wanted me to put the password in the url to make it more secure. Idiots :P

Just a note about the link realmasterX put in, if you read it, it shows you an example sql injection attack which could occur if did not put those checks in place.

(the english version of the link just click on the link and change the /de/ to /en/ or prefered language-code)

Quote

Example 2. An example SQL Injection Attack

<?php
// Query database to check if there are any matching users
$query = "SELECT * FROM users WHERE user='{$_POST['username']}' AND password='{$_POST['password']}'";
mysql_query($query);

// We didn't check $_POST['password'], it could be anything the user wanted! For example:
$_POST['username'] = 'aidan';
$_POST['password'] = "' OR ''='";

// This means the query sent to MySQL would be:
echo $query;
?>

The query sent to MySQL:

SELECT * FROM users WHERE name='aidan' AND password='' OR ''=''

This would allow anyone to log in without a valid password.


Quiet a nice little example i thought i'd point out
0

#6 User is offline   assasinkilla 

  • Private
  • Icon
  • Group: Members
  • Posts: 1
  • Joined: 03-April 07

Posted 03 April 2007 - 05:42 PM

Please guys can you help me with mySQL, i just begin on that and i need it urgent, can you tell me what to do, i created a database, i created 2 tables now? :S... TY A LOT!.. For more info about my web, www.ffateam.page.tl about what hosting im using www.awardspace.com TY A LOT IF U EXPLAIN ME GOOD!!!
0

#7 User is offline   ezechiel 

  • Private
  • Icon
  • Group: Members
  • Posts: 11
  • Joined: 15-June 07

Posted 19 June 2007 - 03:30 AM

Hi there,

to prevent SQL injection, you can also use sprintf.
Google and wiki are your friends if you want to know more :P

You could also use an encryption (never store plain passwords in a database!)
and above, use salting.

This is an example of what I used. But please be gentle on comment:
I'm a complete n00b :unsure:

	 /*
	* 
	* @access remote 
	*/
	function let_in($user, $pass)
	{
		$pass = trim($pass);
		$salt = "V03NAW3075NPV073X58Y35NACQPAZPOVNZ90A50
				   9VB83Z27BV82N0A8X94J09U3VN798X365T98P23Y";
		$pass = md5(trim($salt.$pass));
		$sql77 = sprintf("SELECT client_id AS ID, name AS Name FROM client
							   WHERE name = '".$user."' AND passwd = '".$pass."'");
		$id = mysql_query($sql77);
				 
		return $id;
		NetDebug::trace($user);
   }


If you add the session stuff, it will be even more secure, but this is beyond my capabilities for the moment.
0

#8 User is offline   mas0 

  • Private First Class
  • Icon
  • Group: Members
  • Posts: 20
  • Joined: 31-October 05

Posted 19 June 2007 - 03:54 AM

I use a different technique; stored procedures with parameters. Instead of using a string query of the type select * from [table] where ... i have the procedure stored in my database. call it with parameters. Instead of select * i use select count(*) and in my code i would check if the returned value is 1.
0

#9 User is offline   ezechiel 

  • Private
  • Icon
  • Group: Members
  • Posts: 11
  • Joined: 15-June 07

Posted 20 June 2007 - 03:56 AM

View Postmas0, on Jun 19 2007, 11:54 AM, said:

Instead of select * i use select count(*) and in my code i would check if the returned value is 1.


Yes, this is also a good one. It is very widely used.
When i first learned sql injection, the example was to pass trough a login system like this.
But I couldn't use that kind of login-check because of a lack of knowledge in PHP and thus security issues with Flash and amfPHP when not using SSL. Otherwise I would have used this option because it seems easier to me.

Good idea to put it in a procedure ;)
0

#10 User is offline   Ken Anderson 

  • Private
  • Icon
  • Group: Members
  • Posts: 1
  • Joined: 22-September 09

Posted 22 September 2009 - 01:38 PM

Check out the below link before you play with MD5. Using PBKDF2 Standard uses salt and adds an a stronger level of security. I fell in love with it the first time I laid eyes on the script!

http://www.itnewb.co...PBKDF2-Standard

Cheers,

Ken

View Postezechiel, on 19 June 2007 - 04:30 AM, said:

Hi there,

to prevent SQL injection, you can also use sprintf.
Google and wiki are your friends if you want to know more :P

You could also use an encryption (never store plain passwords in a database!)
and above, use salting.

This is an example of what I used. But please be gentle on comment:
I'm a complete n00b :unsure:

	 /*
	* 
	* @access remote 
	*/
	function let_in($user, $pass)
	{
		$pass = trim($pass);
		$salt = "V03NAW3075NPV073X58Y35NACQPAZPOVNZ90A50
				   9VB83Z27BV82N0A8X94J09U3VN798X365T98P23Y";
		$pass = md5(trim($salt.$pass));
		$sql77 = sprintf("SELECT client_id AS ID, name AS Name FROM client
							   WHERE name = '".$user."' AND passwd = '".$pass."'");
		$id = mysql_query($sql77);
				 
		return $id;
		NetDebug::trace($user);
   }


If you add the session stuff, it will be even more secure, but this is beyond my capabilities for the moment.

0

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users

  • Share



Our Sponsors:


SwiftLayer Affiliate Web Hosting