Hello,
I’ve recently built around 6 or so web sites which have all used the same kind of Login form with PHP.
However, I’m wondering how ‘secure’ it really is, and wondered if any kind SitePointers would be able to ‘audit’ the code.
I understand there’s a lot of code to look over but I would really appreciate any help at all.
The scripts allow a user to register, log in and then log out.
SignUp.php
<?php
include ('includes/functions.php');
include ('includes/config.inc.php');
include('includes/header.php');
$ip = getenv("REMOTE_ADDR");
$hr = getenv("HTTP_REFERER");
$hst = gethostbyaddr( $_SERVER['REMOTE_ADDR'] );
$ua = $_SERVER['HTTP_USER_AGENT'];
// If Form Submitted
if (isset($_POST['saveForm'])) {
if (isset($_SESSION['token']) && $_POST['token'] == $_SESSION['token']) {
// valid token
} else {
header("Location: /signup/signout.php");
}
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
require_once('connect.php');
// Start to set & clean-up variables
// Check for a name.
if (eregi ('^[[:alpha:]\\.\\' \\-]{2,30}$', stripslashes(trim($_POST['name'])))) {
//$name = escape_data($_POST['name']);
$name = substr($name,0,30);
} else {
$name = FALSE;
$errmessage = TRUE;
}
// validate age
$age = getIntValue($_POST['age']);
// validate & confirm email address
$email = $_POST['email'];
if(eregi("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,3})$", $email)) {
$email = stripslashes(strip_tags(trim(strtolower($_POST['email']))));
$email = substr($email,0,120);
} else {
$email = FALSE;
$errmessage = TRUE;
}
$email2 = $_POST['email2'];
if(eregi("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,3})$", $email2)) {
$email2 = stripslashes(strip_tags(trim(strtolower($_POST['email2']))));
$email2 = substr($email2,0,120);
} else {
$email2 = FALSE;
$errmessage = TRUE;
}
if ($email == $email2) {
$e = TRUE;
} else {
$e = FALSE;
$errmessage = TRUE;
}
// Terms
$terms = (isset($_POST['terms'])) ? TRUE : FALSE;
// time stamp - watch our for multiple submissions
if (strlen($_POST['stamp']) == 32) {
$s = escape_data($_POST['stamp']);
} else {
$s = FALSE;
$errmessage = TRUE;
}
// Check if all fields have been completed
if ($e) {
if(!isset($name,$age,$e,$terms,$s) || empty($name) || empty($email) || empty($email2) || empty($age) || empty($terms) || empty($s)) {
$feedbackstyle = "error";
$feedback = "Please complete ALL the form fields.";
} else {
// Make sure the email address is available.
$email = mysql_real_escape_string($email);
$query = "SELECT id FROM pusers WHERE email='$email'";
$result = mysql_query($query);
if (mysql_num_rows($result) == 0) { // Available.
$pass = createRandomPassword();
$salt = randomString();
// prepend the salt to the password
$p = $salt . sha1($salt.$pass);
$ipaddress = $_SERVER['REMOTE_ADDR'];
$name = mysql_real_escape_string($name);
$age = mysql_real_escape_string($age);
$s = mysql_real_escape_string($s);
$result = mysql_query("INSERT INTO pusers(name,age,email,password,date_added,ip,timestamp) VALUES('$name','$age','$email','$p',NOW(),'$ip','$s') LIMIT 1");
if (mysql_affected_rows() == 1) { // If it ran OK.
// Send the email.
$body = "Thank you for signing up for an account with Profiler.";
$body .= "\
\
Your temporary password is ".$pass;
mail($_POST['email'], 'Profiler - Account Confirmation', $body, 'From: no-reply@meownsite.co.uk');
$feedbackstyle = "success";
$feedback = "Great success! Grab your Password in your Inbox and Log In.";
}
}
}
}
}
?>
<form id="form1" name="form1" class="wufoo leftLabel" autocomplete="off" enctype="multipart/form-data" method="post" action="<?php echo(''.htmlentities($_SERVER["PHP_SELF"]).''); ?>">
<input type="hidden" name="token" value="<?php echo $token; ?>" />
<div class="info">
<h2>Sign up</h2>
<div>Complete the form below to sign-up at our web site.</div>
</div>
<?php
if (isset($feedback)) {
echo '<div class="' . $feedbackstyle . '">';
echo $feedback;
echo '</div>';
}
?>
<ul>
<li id="foli1">
<label class="desc" id="title1" for="name">Name<span id="req_1" class="req">*</span></label>
<div>
<input id="name" name="name" type="text" class="field text medium" value="<?php echo (isset($_POST['name'])) ? htmlspecialchars($_POST['name']) : ''; ?>" maxlength="255" tabindex="1" <?php if ((isset($_POST['saveForm'])) && ($name == FALSE)) { echo 'style="border:2px solid red"'; } ?> />
<label for="name">Must be between <var id="rangeMinMsg1">3</var> and <var id="rangeMaxMsg1">50</var> characters. <em class="currently">Currently Used: <var id="rangeUsedMsg1">0</var> characters.</em></label>
</div>
</li>
<li id="foli4">
<label class="desc" id="title4" for="age">Age<span id="req_4" class="req">*</span></label>
<div>
<input id="age" name="age" type="text" class="field text small" value="<?php echo (isset($_POST['age'])) ? htmlspecialchars($_POST['age']) : ''; ?>" maxlength="255" tabindex="3" <?php if ((isset($_POST['saveForm'])) && ($age == FALSE)) { echo 'style="border:2px solid red"'; } ?> />
<label for="age">Enter a number between <var id="rangeMinMsg4">15</var> and <var id="rangeMaxMsg4">130</var>.</label>
</div>
</li>
<li id="foli7">
<label class="desc" id="title7" for="email">Email<span id="req_7" class="req">*</span></label>
<div>
<input id="email" name="email" type="text" class="field text medium" value="<?php echo (isset($_POST['email'])) ? htmlspecialchars($_POST['email']) : ''; ?>" maxlength="255" tabindex="4" <?php if ((isset($_POST['saveForm'])) && ($email == FALSE)) { echo 'style="border:2px solid red"'; } ?> />
</div>
</li>
<li id="foli8">
<label class="desc" id="title8" for="email2">Confirm Email<span id="req_8" class="req">*</span></label>
<div>
<input id="email2" name="email2" type="text" class="field text medium" value="<?php echo (isset($_POST['email2'])) ? htmlspecialchars($_POST['email2']) : ''; ?>" maxlength="255" tabindex="5" <?php if ((isset($_POST['saveForm'])) && (($email2 == FALSE) OR ($e == FALSE))) { echo 'style="border:2px solid red"'; } ?> />
</div>
</li>
<li id="foli314">
<label class="desc" id="title314" for="terms">Terms & Conditions</label>
<div class="col">
<span>
<input id="terms" name="terms" type="checkbox" class="field checkbox" value="yes" tabindex="8" <?php if(isset($_POST['terms']) && $_POST['terms'] == 'yes') { echo 'checked="checked"'; } ?> />
<label class="choice" for="terms">I agree <?php if ((isset($_POST['saveForm'])) && ($terms == FALSE)) { echo '<span style="error">Please tick box.</span>'; } ?></label>
</span>
</div>
</li>
<li class="buttons">
<input id="saveForm" name="saveForm" class="btTxt submit" type="submit" value="Submit" />
</li>
</ul>
<input type="hidden" name="stamp" id="stamp" value="<?php echo md5(uniqid(rand(),true)); ?>" />
</form>
</div><!--container-->
<img id="bottom" src="images/bottom.png" alt="" />
<?php
include('includes/footer.php');
?>
SignIn.php
<?php
include ('includes/functions.php');
include ('includes/config.inc.php');
include('includes/header.php');
$ip = getenv("REMOTE_ADDR");
$hr = getenv("HTTP_REFERER");
$hst = gethostbyaddr( $_SERVER['REMOTE_ADDR'] );
$ua = $_SERVER['HTTP_USER_AGENT'];
if (isset($_POST['saveForm'])) { // Check if the form has been submitted.
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
$_SESSION['token_time'] = time();
require_once ('connect.php'); // Connect to the Database.
if (checkNotEmpty($_POST['email'])) {
if ((strlen($_POST['email']) > '80') || (strlen($_POST['email']) < '7')) {
$email = FALSE;
} else {
$email = strtolower(strip_tags($_POST['email']));
}
} else {
$email = FALSE;
}
if (checkNotEmpty($_POST['password'])) {
if ((strlen($_POST['password']) > '30') || (strlen($_POST['password']) < '8')) {
$p = FALSE;
} else {
$p = strtolower(strip_tags($_POST['password']));
}
} else {
$p = FALSE;
}
if (strlen($_POST['stamp']) == 32) {
$s = TRUE;
}
if ($email && $p && $s) { // If everything's OK.
// clean up for database
$email = mysql_real_escape_string($email);
$ip = mysql_real_escape_string($ip);
// basic brute force protection
/*$ip = $_SERVER['REMOTE_ADDR'];
$sql = "SELECT id, email FROM login_attempts WHERE email = '$email' AND ip = '$ip'";
$res = mysql_query($sql);
if (mysql_num_rows($res) > '8') {
$feedbackstyle = "error";
$feedback = "You have made 8 failed login attempts.<br />Your Account has now been blocked.";
include ('includes/footer.php');
exit;
}
mysql_free_result($res);*/
// Query the Database.
$query = "SELECT id, email, name FROM pusers WHERE (email='$email' AND password = CONCAT(SUBSTRING(password, 1, 32), SHA1(CONCAT(SUBSTRING(password, 1, 32), '$p')))) AND disabled = 'N' LIMIT 1";
$result = mysql_query ($query);
// A match was made
if (mysql_num_rows($result) == 1) {
// Register the values and redirect.
$row = mysql_fetch_array($result, MYSQL_NUM);
mysql_free_result($result);
mysql_close(); // Close the db connection.
$_SESSION['name'] = escape_data(htmlspecialchars($row[2]));
$_SESSION['email'] = $row[1];
$_SESSION['u_id'] = $row[0];
$user_id = $row[0];
session_regenerate_id();
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['timestamp'] = time();
$_SESSION['theagent'] = md5($_SERVER['HTTP_USER_AGENT']);
$_SESSION['HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
// Start defining the URL
$url = 'http://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']);
// Check for trailing slash.
if ((substr($url, -1) == '/') OR (substr($url, -1) == '\\\\') ) {
$url = substr ($url, 0, -1); // Chop off the slash.
}
// Add the Page
$url .= '/index.php';
ob_end_clean(); // Delete the buffer.
header("Location: $url");
exit(); // Quit the script.
} else { // No match was made.
// Alert Administrator of Failed Login Attempt
$to = "michael@meownsite.co.uk";
$subject = "Profiler | Failed Login Attempt";
$message = "Hello\
\
Email: $email\
\
IP: $ip";
$headers = 'From: no-reply@meownsite.co.uk' . "\\r\
" .
'Reply-To: no-reply@meownsite.co.uk' . "\\r\
" .
'X-Mailer: PHP/' . phpversion();
mail($to, $subject, $message, $headers);
// log failed attempt, in case brute force
$ip = $_SERVER['REMOTE_ADDR'];
$sql = "INSERT INTO login_attempts VALUES ('','$email','$ip',now()) LIMIT 1";
mysql_query($sql);
$feedbackstyle = "error";
$feedback = "Either the email address and password entered do not match those on file, or you have not yet activated your account.";
$sqler = "SELECT * FROM login_attempts WHERE ip = '$ip' AND date_added >= (NOW()-1)";
$reser = mysql_query($sqler);
if (mysql_num_rows($reser) > 3) {
$sqlupdate = "UPDATE pusers SET disabled = 'Y' WHERE email = $email";
mysql_query($sqlupdate);
// uh-oh notify
$to = "michael@michaelmcg.co.uk";
$subject = "Profiler | 3 Failed Login Attempts...";
$message = "Hello\
\
Email: $email\
\
IP: $ip";
$headers = 'From: no-reply@meownsite.co.uk' . "\\r\
" .
'Reply-To: no-reply@meownsite.co.uk' . "\\r\
" .
'X-Mailer: PHP/' . phpversion();
mail($to, $subject, $message, $headers);
}
mysql_free_result($reser);
}
} else { // If everything wasn't OK.
$feedbackstyle = "error";
$feedback = "Please try again.";
}
} // End of Submit conditional.
?>
<form id="form1" name="form1" class="wufoo leftLabel" autocomplete="off" enctype="multipart/form-data" method="post" action="<?php echo(''.htmlentities($_SERVER["PHP_SELF"]).''); ?>">
<div class="info">
<h2>Sign in</h2>
<div>Complete the form below to sign-in to our web site.</div>
</div>
<?php
if (isset($feedback)) {
echo '<div class="' . $feedbackstyle . '">';
echo $feedback;
echo '</div>';
}
?>
<ul>
<li id="foli7">
<label class="desc" id="title7" for="email">Email<span id="req_7" class="req">*</span></label>
<div>
<input id="email" name="email" type="text" class="field text medium" value="<?php echo (isset($_POST['email'])) ? htmlspecialchars($_POST['email']) : ''; ?>" maxlength="80" tabindex="4" <?php if ((isset($_POST['saveForm'])) && ($email == FALSE)) { echo 'style="border:2px solid red"'; } ?> />
</div>
</li>
<li id="foli414">
<label class="desc" id="title414" for="password">Password<span id="req_414" class="req">*</span></label>
<div>
<input id="password" name="password" type="password" class="field text medium" value="<?php echo (isset($_POST['password'])) ? htmlspecialchars($_POST['password']) : ''; ?>" maxlength="30" tabindex="9" <?php if ((isset($_POST['saveForm'])) && ($p == FALSE)) { echo 'style="border:2px solid red"'; } ?> />
<label for="password">Must be between <var id="rangeMinMsg414">8</var> and <var id="rangeMaxMsg414">30</var> characters. <em class="currently">Currently Used: <var id="rangeUsedMsg414">0</var> characters.</em></label>
</div>
</li>
<li class="buttons">
<input id="saveForm" name="saveForm" class="btTxt submit" type="submit" value="Submit" />
</li>
</ul>
<input type="hidden" name="stamp" id="stamp" value="<?php echo md5(uniqid(rand(),true)); ?>" />
</form>
</div><!--container-->
<img id="bottom" src="images/bottom.png" alt="" />
<?php
include('includes/footer.php');
?>
Index.php
<?php # index.php
include ('includes/functions.php');
include ('includes/config.inc.php');
include('includes/header.php');
if (isset($_SESSION['HTTP_USER_AGENT'])) {
if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT'])) {
header("Location: /signup/signout.php");
}
} else {
$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);
}
require_once ('connect.php'); // Connect to the Database.
$clean = array();
$html = array();
$clean['name'] = $_SESSION['name'];
$html['name'] = htmlentities($clean['name'], ENT_QUOTES, 'UTF-8');
echo "<h2>Welcome, {$html['name']}</h2>";
echo "<p><strong>Not {$html['name']}? <a href='signout.php'>Click here</a>.</strong></p>";
include ('includes/footer.php');
?>
Header.php
<?php
ob_start();
session_start();
//error_reporting(E_ALL & ~E_NOTICE);
$currentFile = $_SERVER["SCRIPT_NAME"];
$foo = $_SERVER['PHP_SELF'];
if (isset($_SESSION['u_id']) && ($currentFile == '/signup/signin.php')) {
header("Location: index.php");
}
if ((!isset($_SESSION['u_id'])) && ($currentFile == '/signup/index.php')) {
header("Location: signin.php");
}
$ip = $_SERVER['REMOTE_ADDR'];
if (isset($_SESSION['ip'])) {
if ($_SESSION['IP'] != $_SERVER['REMOTE_ADDR']) {
header("Location: /signup/signout.php");
}
}
if (isset($_SESSION['timestamp'])) {
if ((time() - $_SESSION['timestamp']) > 1800) {
header("Location: /signup/signout.php");
} else {
$_SESSION['timestamp'] = time();
}
}
require_once ('connect.php'); // Connect to the Database.
?>
<!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>Profiler</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- CSS -->
<link rel="stylesheet" href="css/structure.css" type="text/css" />
<link rel="stylesheet" href="css/form.css" type="text/css" />
</head>
<body id="public">
<img id="top" src="images/top.png" alt="" />
<div id="container">
Footer.php
</body>
</html>
<?php
if (isset($_POST['saveForm'])) {
// close my db connection
mysql_close($dbc);
}
?>
Snippet from Functions.php
function checkNotEmpty($s) {
return (trim($s) !== '');
}
function getIntValue($s) {
if (!is_numeric($s)) {
return false;
} else {
return (int)$s;
}
}
Like I say I understand there is a large amount of code on display here, but I would really value some of the professionals taking a look over it and maybe making same obvious notes of things I haven’t considered.
I’ve tried to consider things like XSS and SQL Injection.
I’m going to use htaccess/htpasswd on my administrator directory as well as try enforce a strict password scheme for users.
Many thanks for any assistance