Featured

    Featured Posts

    Social Icons

Loading...

Configure mySQL Database

  1. Create a MySQL database.
In this guide we will create a database called "secure_login".
See how to Create-a-Database-in-Phpmyadmin.
Or you can use the SQL code below will create one for you.

Create Database Code:
CREATE DATABASE `secure_login` ;

Note: Some hosting services don't allow you to create a database through phpMyAdmin,Learn how to do it in cPanel.

  1. 2
Create a user with only SELECT, UPDATE and INSERT privileges.
This means that if there was ever a breach of security in our script the hacker couldn't delete or drop anything from our database. Using this user you can get by doing pretty much anything you would want to in your application. If your really paranoid, create a different user for each function.

    • User: "sec_user"
    • Password: "eKcGZr59zAa2BEWU"


Create User Code:
CREATE USER 'sec_user'@'localhost' IDENTIFIED BY 'eKcGZr59zAa2BEWU';
GRANT SELECT, INSERT, UPDATE ON `secure_login`.* TO 'sec_user'@'localhost';

Note: It is a good idea to change the password in the code above when running on your own server. (Make sure you change your PHP code also.) Remember it doesn't need to be a password that you can remember so make is as complicated as possible. Here's arandom password generator.
  1. 3
Create a MySQL table named "members".
The code below creates a table with 5 fields (id, username, email, password, salt).

Create the "members" table:
CREATE TABLE `secure_login`.`members` (
  `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
  `username` VARCHAR(30) NOT NULL, 
  `email` VARCHAR(50) NOT NULL, 
  `password` CHAR(128) NOT NULL, 
  `salt` CHAR(128) NOT NULL
) ENGINE = InnoDB;

We use the CHAR datatype for fields we know the length of, as the fields "password" and "salt" will always be 128 characters long. Using CHAR here saves on processing power.
  1. 4
Create a table to store login attempts.
We will use this table to store login attempts for a user, this is how we will stop brute force attacks.

Create the "login_attempts" table:
CREATE TABLE `secure_login`.`login_attempts` (
  `user_id` int(11) NOT NULL,
  `time` VARCHAR(30) NOT NULL 
) ENGINE=InnoDB
  1. 5
Create test row in table "members".
As we are not creating a registration page, it will be important to be able to test your login script. Below is the script to create a user with these details:
    • Username: test_user
    • Email: test@example.com
    • Password: 6ZaxN2Vzm9NUJT2y

Add test user:
INSERT INTO `secure_login`.`members` VALUES(1, 'test_user', 'test@example.com', '00807432eae173f652f2064bdca1b61b290b52d40e429a7d295d76a71084aa96c0233b82f1feac45529e0726559645acaed6f3ae58a286b9f075916ebf66cacc', 'f9aab579fc1b41ed0c44fe4ecdbfcdb4cb99b9023abb241a6db833288f4eea3c02f76e0d35204a8695077dcf81932aa59006423976224be0390395bae152d4ef');
Create Database Connection Page
  1. 1
Create Database Connection Page.
This is the php code that we will use to connect to our mySQL database. Create a new php file called "db_connect.php" and add the code below. You can then include the file onto any page you wish to connect to the database.

Database Connect (db_connect.php):
define("HOST", "localhost"); // The host you want to connect to.
define("USER", "sec_user"); // The database username.
define("PASSWORD", "eKcGZr59zAa2BEWU"); // The database password. 
define("DATABASE", "secure_login"); // The database name.

$mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);
// If you are connecting via TCP/IP rather than a UNIX socket remember to add the port number as a parameter.
Create PHP Functions
These functions will do all the processing of the login script. Add all of the functions to a page called "functions.php".
  1. 1
Securely start a PHP session.
It important not to just put "session_start();" on the top of every page that you want to use php sessions, If you're really concerned about security then this is how you should do it. We are going to create a function called "sec_session_start", this will start a php session in a secure way. You should call this function at the top of any page you wish to access a php session variable. If you are really concerned about security and the privacy of your cookies, have a look at this article Create-a-Secure-Session-Managment-System-in-Php-and-Mysql.

Secure Session Start Function:
function sec_session_start() {
        $session_name = 'sec_session_id'; // Set a custom session name
        $secure = false; // Set to true if using https.
        $httponly = true; // This stops javascript being able to access the session id. 

        ini_set('session.use_only_cookies', 1); // Forces sessions to only use cookies. 
        $cookieParams = session_get_cookie_params(); // Gets current cookies params.
        session_set_cookie_params($cookieParams["lifetime"], $cookieParams["path"], $cookieParams["domain"], $secure, $httponly); 
        session_name($session_name); // Sets the session name to the one set above.
        session_start(); // Start the php session
        session_regenerate_id(); // regenerated the session, delete the old one.  
}

This function makes your login script a whole lot more secure. It stops hackers been able to access the session id cookie through javascript (For example in an XSS attack).
Also by using the "session_regenerate_id()" function, which regenerates the session id on every page reload, helping prevent session hijacking.

Note: If you are using https in your login application set the "$secure" variable to true.
  1. 2
Create Login Function.
This function will check the email and password against the database, it will return true if there is a match.

Secure Login Function:
function login($email, $password, $mysqli) {
   // Using prepared Statements means that SQL injection is not possible. 
   if ($stmt = $mysqli->prepare("SELECT id, username, password, salt FROM members WHERE email = ? LIMIT 1")) { 
      $stmt->bind_param('s', $email); // Bind "$email" to parameter.
      $stmt->execute(); // Execute the prepared query.
      $stmt->store_result();
      $stmt->bind_result($user_id, $username, $db_password, $salt); // get variables from result.
      $stmt->fetch();
      $password = hash('sha512', $password.$salt); // hash the password with the unique salt.

      if($stmt->num_rows == 1) { // If the user exists
         // We check if the account is locked from too many login attempts
         if(checkbrute($user_id, $mysqli) == true) { 
            // Account is locked
            // Send an email to user saying their account is locked
            return false;
         } else {
         if($db_password == $password) { // Check if the password in the database matches the password the user submitted. 
            // Password is correct!


               $user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.

               $user_id = preg_replace("/[^0-9]+/", "", $user_id); // XSS protection as we might print this value
               $_SESSION['user_id'] = $user_id; 
               $username = preg_replace("/[^a-zA-Z0-9_\-]+/", "", $username); // XSS protection as we might print this value
               $_SESSION['username'] = $username;
               $_SESSION['login_string'] = hash('sha512', $password.$user_browser);
               // Login successful.
               return true;    
         } else {
            // Password is not correct
            // We record this attempt in the database
            $now = time();
            $mysqli->query("INSERT INTO login_attempts (user_id, time) VALUES ('$user_id', '$now')");
            return false;
         }
      }
      } else {
         // No user exists. 
         return false;
      }
   }
}
  1. 3
Brute Force Function.
Brute force attacks are when a hacker will try 1000s of different passwords on an account, either randomly generated passwords or from a dictionary. In our script if a user account has a failed login more than 5 times their account is locked.

Create checkbrute function:
function checkbrute($user_id, $mysqli) {
   // Get timestamp of current time
   $now = time();
   // All login attempts are counted from the past 2 hours. 
   $valid_attempts = $now - (2 * 60 * 60); 

   if ($stmt = $mysqli->prepare("SELECT time FROM login_attempts WHERE user_id = ? AND time > '$valid_attempts'")) { 
      $stmt->bind_param('i', $user_id); 
      // Execute the prepared query.
      $stmt->execute();
      $stmt->store_result();
      // If there has been more than 5 failed logins
      if($stmt->num_rows > 5) {
         return true;
      } else {
         return false;
      }
   }
}


Brute force attacks are hard to prevent a few ways we can prevent them are using a CAPTCHA test, locking user accounts and adding a delay on failed logins, so the user can not login for another 30 seconds.
When faced with this problem most developers simply block the IP address after certain amount of failed logins. With many tools to automate the process, these tools can go through a series of proxies and even change the IP on each request. Blocking all these IP addresses could mean you're blocking legitimate users as well.
  1. 4
Check logged in status.
We do this by checking the the "user_id" and the "login_string" SESSION variables. The "login_string" SESSION variable has the users Browser Info hashed together with the password. We use the Browser Info because it is very unlikely that the user will change their browser mid-session. Doing this helps prevent session hijacking.

Create login_check function:
function login_check($mysqli) {
   // Check if all session variables are set
   if(isset($_SESSION['user_id'], $_SESSION['username'], $_SESSION['login_string'])) {
     $user_id = $_SESSION['user_id'];
     $login_string = $_SESSION['login_string'];
     $username = $_SESSION['username'];

     $user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.

     if ($stmt = $mysqli->prepare("SELECT password FROM members WHERE id = ? LIMIT 1")) { 
        $stmt->bind_param('i', $user_id); // Bind "$user_id" to parameter.
        $stmt->execute(); // Execute the prepared query.
        $stmt->store_result();

        if($stmt->num_rows == 1) { // If the user exists
           $stmt->bind_result($password); // get variables from result.
           $stmt->fetch();
           $login_check = hash('sha512', $password.$user_browser);
           if($login_check == $login_string) {
              // Logged In!!!!
              return true;
           } else {
              // Not logged in
              return false;
           }
        } else {
            // Not logged in
            return false;
        }
     } else {
        // Not logged in
        return false;
     }
   } else {
     // Not logged in
     return false;
   }
}
Create Processing Pages
  1. 1
Create the login processing page (process_login.php).
If following our previous example, this should be named process_login.php.
We will use the mysqli_* set of PHP functions as this is the most up to date mysql extension.

Login processing page (process_login.php)
include 'db_connect.php';
include 'functions.php';
sec_session_start(); // Our custom secure way of starting a php session. 

if(isset($_POST['email'], $_POST['p'])) { 
   $email = $_POST['email'];
   $password = $_POST['p']; // The hashed password.
   if(login($email, $password, $mysqli) == true) {
      // Login success
      echo 'Success: You have been logged in!';
   } else {
      // Login failed
      header('Location: ./login.php?error=1');
   }
} else { 
   // The correct POST variables were not sent to this page.
   echo 'Invalid Request';
}

  1. 2
Create a logout script.
Your logout script must start the session, destroy it and then redirect to somewhere else.

Logout Script (logout.php):
include 'functions.php';
sec_session_start();
// Unset all session values
$_SESSION = array();
// get session parameters 
$params = session_get_cookie_params();
// Delete the actual cookie.
setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]);
// Destroy session
session_destroy();
header('Location: ./');

Note: It might be a good idea to add CSRF protection here as if someone send a link with this page hidden somehow. The user will be logged out.
  1. 3
Registration Page.
To create the password hash you will need to use the following code:

Hash Script:
// The hashed password from the form
$password = $_POST['p']; 
// Create a random salt
$random_salt = hash('sha512', uniqid(mt_rand(1, mt_getrandmax()), true));
// Create salted password (Careful not to over season)
$password = hash('sha512', $password.$random_salt);

// Add your insert to database script here. 
// Make sure you use prepared statements!
if ($insert_stmt = $mysqli->prepare("INSERT INTO members (username, email, password, salt) VALUES (?, ?, ?, ?)")) {    
   $insert_stmt->bind_param('ssss', $username, $email, $password, $random_salt); 
   // Execute the prepared query.
   $insert_stmt->execute();
}

Make sure the value of $_POST['p'] is already hashed from javascript, if you are not using this method because you want to validate the password server side then make sure you hash it.
Create Javascript Files
  1. 1
Create sha512.js file
This file is an implementation in javascript of the hashing algorithm sha512. We will use the hashing function so our passwords don't get sent in plaintext.

The file can be downloaded from pajhome.org.uk
  1. 2
Create forms.js file
This file will handle the hashing of the passwords for any forms.

Javascript form file (forms.js):
function formhash(form, password) {
   // Create a new element input, this will be out hashed password field.
   var p = document.createElement("input");
   // Add the new element to our form.
   form.appendChild(p);
   p.name = "p";
   p.type = "hidden"
   p.value = hex_sha512(password.value);
   // Make sure the plaintext password doesn't get sent.
   password.value = "";
   // Finally submit the form.
   form.submit();
}
Create HTML Pages
  1. 1
Create the login form (login.php).



This is a HTML form with two text fields, named "email" and "password". The Javascript will then generate a hash of the password, and send the "email" and "p" (the hashed password) to the server.

When logging in, it is best to use something that is not public, for this guide we are using the email as the login id, the username can then be used to identify the user. If the email is hidden it adds another variable for hacking accounts.

HTML Login Form:
<script type="text/javascript" src="sha512.js"></script>
<script type="text/javascript" src="forms.js"></script>
<?php
if(isset($_GET['error'])) { 
   echo 'Error Logging In!';
}
?>
<form action="process_login.php" method="post" name="login_form">
   Email: <input type="text" name="email" /><br />
   Password: <input type="password" name="p" id="password"/><br />
   <input type="button" value="Login" onclick="formhash(this.form, this.form.password);" />
</form>

Note: Even though we have encrypted the password so it is not sent in plaintext, it is recommended that you use the https protocol (TLS/SSL) when sending passwords. (See:Network Eavesdropping).
Protecting Pages
  1. 1
Page Protection Script.
One of the most common problems with authentication systems is the developer forgetting to check if the user is logged in. It is very important you use the below code to check that the user is logged in.
Protecting pages:
// Include database connection and functions here.
sec_session_start();
if(login_check($mysqli) == true) {

   // Add your protected page content here!

} else {
   echo 'You are not authorized to access this page, please login. <br/>';
}

Make sure you use this function to check if the user if logged in.
author

This post was written by: Author Name

Your description comes here!

Get Free Email Updates to your Inbox!

Post a Comment

CodeNirvana
Powered by Blogger.
© Copyright News 24
Back To Top