Page 1 of 1
PHP registration/login security
Posted: Fri Apr 06, 2012 1:42 pm
by 62896dude
Hey everyone,
I'm currently constructing a foundational registration/login system that I can use with versatility in any game. To make sure it isn't just the usual system though, I've been putting as many security measures in place as possible without directly impacting the user's maneuverability too much. For example, I put in a Google ReCaptcha, have email verification, and a few other back end checks. My question is, though, what other measures can be taken? I know that there are multiple ways to mess with the database from basic PHP registration, but I don't have the slightest idea on how to protect against those.
If any of you could give some insight into this (especially Chris, as I know that he is quite good with this), that would be extremely helpful.
Thanks!
Re: PHP registration/login security
Posted: Fri Apr 06, 2012 2:14 pm
by Chris
Code please.
Re: PHP registration/login security
Posted: Fri Apr 06, 2012 2:36 pm
by 62896dude
*EDIT: I have just posted my most recent version of each one, with many bugs fixed.
Sure, bear in mind it is still under construction & a few bugs are still being worked out,
Register:
Code: Select all
<html>
<?php
include 'connect.php';
?>
<head>
<title>Register</title>
<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
<style type="text/css">
.style1 {
margin-left: 2px;
}
.style2 {
margin-left: 1px;
}
</style>
</head>
<form action="reguser.php" method="post">
<body>
<fieldset>
<legend>Register</legend>
<b>Username:</b>                 <input type="text" size="25" name="name" maxlength="21" class="style2" /><br/>
<b>Password: </b>                 <input type="password" size="25" name="password" maxlength="32" class="style1" /><br/>
<b>Re-Enter Password: </b> <input type="password" size="25" name="pass2" maxlength="32" /><br/>
<b>Email Address: </b>         <input type="text" size="25" name="email" maxlength="55" /><br/>
<input type="hidden" name="form_submitted" value="1"/>
<form>
<input type="radio" name="sex" value="male" />Male<br />
<input type="radio" name="sex" value="female" />Female
<?php
require_once('recaptchalib.php');
$publickey = "6Le04M8SAAAAAA3lfaw-4xkc3HT1ot7sKAWM0y_A "; // you got this from the signup page
echo recaptcha_get_html($publickey);
?>
</form>
<input type="submit" value="Submit" name="submit" /> <br/>
</fieldset>
</body>
</html>
Reguser:
Code: Select all
<html>
<head>
<title>Register</title>
</head>
<body>
<?php
include ('connect.php');
echo "<center>";
$username=$_POST['name'];
$password=$_POST['password'];
$pass2=$_POST['pass2'];
$email=$_POST['email'];
$gender=$_POST['sex'];
$utext = "$username";
$unon_space = preg_replace("/\s+/", "", $utext);
$userlen = strlen($unon_space);
$ptext = "The quick brown fox";
$pnon_space = preg_replace("/\s+/", "", $ptext);
$passlen = strlen($pnon_space);
strip_tags($username);
strip_tags($password);
$queryString = $_SERVER['QUERY_STRING'];
if (!$queryString){
if($username == '')
{
echo "You did not enter a username!";
echo "<a href='register.php'><input type='button' value='Go Back!' name='button'>";
exit;
}
if ($password == '')
{
echo "You did not enter a password!";
echo "<a href='register.php'><input type='button' value='Go Back!' name='button'>";
exit;
}
if($pass2 == '')
{
echo "You did not re-enter your password!";
echo "<a href='register.php'><input type='button' value='Go Back!' name='button'>";
exit;
}
if ($email == '')
{
echo "You did not enter your email!";
echo "<a href='register.php'><input type='button' value='Go Back!' name='button'>";
exit;
}
if ($gender == '')
{
echo "You did not enter your gender!";
echo "<a href='register.php'><input type='button' value='Go Back!' name='button'>";
exit;
}
if ($userlen < 5)
{
echo "Your username must be at least 5 characters!";
echo "<a href='register.php'><input type='button' value='Go Back!' name='button'>";
exit;
}
if ($passlen < 5)
{
echo "Your username must be at least 5 characters!";
echo "<a href='register.php'><input type='button' value='Go Back!' name='button'>";
exit;
}
$ck_user="SELECT * from players where name='$username'";
$ck_email="SELECT * from players where email='$email'";
if( mysql_num_rows( mysql_query( $ck_user ) ) >= 1 ){
die("There is already a user with that name. Please go back and try again.<br>
<form name=\"back\" action=\"register.php\"
method=\"post\">
<input type=\"submit\" value=\"Try Again\">
</form>
");
}
if( mysql_num_rows( mysql_query( $ck_email ) ) >= 1 ){
die("There is already a user with that email. Please go back and try again.<br>
<form name=\"back\" action=\"register.php\"
method=\"post\">
<input type=\"submit\" value=\"Try Again\">
</form>
");
}
if($password == $pass2)
{
$password=md5($password);
$activationKey = mt_rand() . mt_rand() . mt_rand() . mt_rand() . mt_rand();
$mysql="INSERT into players(user, pass, email, status, activationkey, gender, online, try) VALUES('$username','$password','$email','verify','$activationKey','$gender','0','0')";
$insert=mysql_query($mysql) or die("Could not insert player data");
}
if ($_POST['form_submitted'] == '1') {
##User is registering, insert data until ;we can activate it
echo "An email has been sent to $email with an activation key. Please check your mail to complete registration.";
##Send activation Email
$to = $_POST['email'];
$subject = " New Game Registration";
$message = "Welcome to our website!\r\rYou, or someone using your email address, has completed registration at New Game. You can complete registration by clicking the following link:\rhttp://www.newgame.comlu.com/reguser.php?$activationKey\r\rIf this is an error, ignore this email and you will be removed from our mailing list.\r\rRegards,\ New Game Team";
$headers = 'From: noreply@newgame.comlu.com' . "\r\n" .
'Reply-To: noreply@newgame.comlu.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
mail($to, $subject, $message, $headers);
}
}
elseif ($queryString){
##User isn't registering, check verify code and change activation code to null, status to activated on success
$query = "SELECT * FROM players WHERE activationkey = '$queryString'";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)){
if ($queryString == $row['activationkey']){
echo "Congratulations!" . $row["user"] . " is now the proud new owner of a New Game account.";
$sql="UPDATE players SET activationkey = '', status='activated' WHERE (id = $row[id])";
if (!mysql_query($sql))
{
die('Error: ' . mysql_error());
}
}
}
}
echo "</center>";
?>
</body>
</html>
Re: PHP registration/login security
Posted: Fri Apr 06, 2012 5:36 pm
by Chris
Code: Select all
<?php
$enable_form = true;
$errors = array();
$successes = array();
if( $_SERVER['REQUEST_METHOD'] == 'POST' )
{
// post request has been sent
// validate attributes
if( empty($_POST['username']) || strlen( (string)$_POST['username'] ) == 0 )
{
$errors[] = 'You did not enter a username!';
}
if( empty($_POST['password']) || strlen( (string)$_POST['password'] ) == 0 )
{
$errors[] = 'You did not enter a password!';
}
if( empty($_POST['pass2']) || strlen( (string)$_POST['pass2'] ) == 0 )
{
$errors[] = 'You did not re-enter your password!';
}
if( empty($_POST['email']) || strlen( (string)$_POST['email'] ) == 0 )
{
$errors[] = 'You did not enter a your email!';
}
if( empty($_POST['gender']) )
{
$errors[] = 'You did not enter your gender!';
}
// check if there were any errors
if( count($errors) == 0 )
{
// no errors so far
// continue to further checks
if( strlen( (string)$_POST['username'] ) < 5 )
{
$errors[] = 'Your username must be atleast 5 characters long!';
}
if( strlen( (string)$_POST['password'] ) < 5 )
{
$errors[] = 'Your password must be atleast 5 characters long!';
}
if( strlen( (string)$_POST['username'] ) > 21 )
{
$errors[] = 'Username cannot be longer than 21 characters!';
}
}
// second error check
if( count($errors) == 0 )
{
// will need to connect to database now
include 'localhost.php';
$username_query = mysql_query("SELECT `id`
FROM `players`
WHERE `name` = '". mysql_real_escape_string( (string)$_POST['username'] ) ."';");
if( mysql_num_rows($username_query) != 0 )
{
$errors[] = 'There is already a user with that name.';
}
if( $_POST['password'] != $_POST['pass2'] )
{
$errors[] = 'Passwords do not match.';
}
$email_query = mysql_query("SELECT `id`
FROM `players`
WHERE `email` = '". mysql_real_escape_string( (string)$_POST['email'] ) ."';");
if( mysql_num_rows($username_query) != 0 )
{
$errors[] = 'There is already a user with that email.';
}
}
// final error check
if( count($errors) == 0 )
{
// no errors found
// register new user
$activation_key = mt_rand() . mt_rand() . mt_rand() . mt_rand() . mt_rand();
mysql_query("INSERT INTO `players` (`name`,`pass`,`email`,`status`,`activationkey`,`gender`,`online`,`try`)
VALUES (
'". mysql_real_escape_string( (string)$_POST['username'] ) ."',
'". md5( (string)$_POST['password'] ) ."',
'". mysql_real_escape_string( (string)$_POST['email'] ) ."',
'verify',
'". $activationkey ."',
'". (int)$_POST['gender'] ."',
0,
0 );");
mail( (string)$_POST['email'],
'New Game Registration',
"Welcome to our website!\r\r
You, or someone using your email address, has completed registration at New Game. You can complete registration by clicking the following link:\r
http://www.newgame.comlu.com/activate.php?$activationKey\r\r
If this is an error, ignore this email and you will be removed from our mailing list.\r\r
Regards,\r
New Game Team",
'From: noreply@newgame.comlu.com
Reply-To: noreply@newgame.comlu.com');
$enable_form = false;
$successes[] = 'Successfully registered. Please check your email for the activation process.';
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Register</title>
<script type="text/javascript" src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
<style type="text/css">
label {
font-weight: bold;
display: block;
}
</style>
</head>
<body>
<?php if( count($errors) > 0 ) : ?>
<h3>Error</h3>
<ul class="errors">
<?php foreach($errors as $error) : ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php if( count($successes) > 0 ) : ?>
<h3>Success</h3>
<ul class="errors">
<?php foreach($successes as $success) : ?>
<li><?php echo $success; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php if( $enable_form ) : ?>
<form action="register.php" method="post">
<fieldset>
<legend>Register</legend>
<label>
Username:
<input type="text" size="25" name="username" maxlength="21" />
</label>
<label>
Password:
<input type="password" size="25" name="password" />
</label>
<label>
Re-Enter Password:
<input type="password" size="25" name="pass2" />
</label>
<label>
Email Address:
<input type="text" size="25" name="email" />
</label>
Sex:<br />
<label>
<input type="radio" name="gender" value="1" />
Male
</label>
<label>
<input type="radio" name="gender" value="2" />
Female
</label>
<label>
<input type="radio" name="gender" value="0" />
Yes please
</label>
<?php
//require_once('recaptchalib.php');
//$publickey = "6Le04M8SAAAAAA3lfaw-4xkc3HT1ot7sKAWM0y_A "; // you got this from the signup page
//echo recaptcha_get_html($publickey);
?>
<input type="submit" value="Submit" name="submit" />
</fieldset>
</form>
<?php endif; ?>
</body>
</html>
Haven't tested it, should run. You might want to rethink your activation process.
Also keep player accounts seperate from their login details. (use a users table and players table)
Re: PHP registration/login security
Posted: Fri Apr 06, 2012 5:48 pm
by 62896dude
Okay, thanks so much! I'll go through this and make the changes to my code.
Thanks again!
~Kevin
Re: PHP registration/login security
Posted: Fri Apr 06, 2012 5:53 pm
by Chris
Should have tested, there were a lot of little bugs

.
Re: PHP registration/login security
Posted: Mon Apr 09, 2012 8:59 pm
by cxn
Hello Chris, I was wondering why you would want to have seperate tables please? Thank you
Re: PHP registration/login security
Posted: Mon Apr 09, 2012 9:39 pm
by Jackolantern
cxn wrote:Hello Chris, I was wondering why you would want to have seperate tables please? Thank you
It makes your code more versatile. Once data is married together into a table, it can be hell to separate it out later and can break existing code (not a good thing obviously). A "users" table should not be part of the "character" (or whatever you want to call it) because it is not the same thing. What if later on you want to allow one user to have multiple characters? If they are the same, you have given yourself a mountain of work to separate them out which you will have to do before you can have multiple-character accounts. There are many other cases in which you may want to address the users or the characters separately, such as alternate logins to various services, such as a separate account maintenance login page (if they are one table, by having an account login page where users can update their email or perform other such service activities, you are just compromising your character data by loading that in and making it accessible when their activity, such as updating their email, does not require it). It is just a good idea to keep them separate from the start.
By keeping each table only dealing with one thing, you increase the security of your database because every piece of data you make accessible is just another thing that your own code can mess up.
Re: PHP registration/login security
Posted: Mon Apr 09, 2012 10:04 pm
by Ark
hey Chris how can you hack a mysql db by insterting javascript on an input tag? Or maybe by the url too?

Re: PHP registration/login security
Posted: Mon Apr 09, 2012 10:57 pm
by Chris
You can't. What you could do with JavaScript is inject a script that sends user session id cookies with ajax to your server. You could then use the session ids to session hijack other peoples sessions and possibly find something to work with from there. It's impossible to straight hack a MySQL database with JavaScript injection.
To prevent JavaScript or other HTML elements from being injected. Run
htmlentities every time you display user submitted data on your site. You could also use strip_tags(). But I personally find this method reduces the user experience.
Code: Select all
$myQuery = mysql_query("SELECT `whatever` FROM `the_table` WHERE `something` = 1");
$myArray = mysql_fetch_assoc($myQuery);
echo htmlentities($myArray['whatever']);
cxn wrote:Hello Chris, I was wondering why you would want to have seperate tables please? Thank you
Read what Jack said. And also it reduces the chance of a hacker being able to find and alter data as easy, it won't prevent anything however. Keeping things seperate means if a hacker does manage to drop a table or two, there is a high chance you wont loose everything.
A users table should only contain the minimum amount of data. Usually I keep mine at 4 fields. An id, username, password and email address.