Better Hashing Password in PHP

Every developer should know that storing any type of password in plain text is the worst possible decision anyone can make in a secure environment. Between security and confidentiality which one will you choose? Nowadays hacking are perform through social engineering or an inside job, by an employee or trusted person. How exactly confident are you towards securing your stuff and confidentiality of your user? Most of us will know that the Reddit suffer from such problem when all their username and password were compromised as their password wasn't hashed and stored as plain text. And twitter was attacked through social engineering recently. We won't want this to happen to us right? Therefore, in this article you will get to know some ways to better hash your password in PHP and some ways to improve your security.

What is Hashing?

Hashing is a term used in encryption to perform a deterministic procedure that takes an arbitrary block of data and returns a fixed-size bit string. Any accidental or intentional attempt to change the data will change the hash value. Moreover, different message will have different hash value. There should not be an exact hash value with different message. And it is infeasible to find a message that has a given hash. Hence, many information security application uses hashing to protect or authenticate the confidentiality of the content of the application such as digital signatures, message authentication codes (MACs), and other forms of authentication.

Authenticate User

We use cryptographic hash function to hash our password. And all of us should not be aware of what is being placed as password in the table. So how do we authenticate these users password since hash value is a one way encryption? This can easily be achieve through comparing the hash value against the one user has keyed in and the one stored in our database!

Rainbow table Attack

A rainbow table attack is a form of lookup table that aim to decode the hash value in order to make hashing feasible to find a message that has a given hash. Rainbow table attack is usually used against cryptographic hash function after they have retrieved a hash value. However, we can better protect ourselves by adding SALT onto our plain text to make it more infeasible for rainbow table to retrieve pain text with a given hash value.

SHA-1 and MD5

We all know that hashing is necessary in term of any password. But i would still like to stress such importance. We are very dependency on encryption algorithm such as MD5 or SHA-1. However, these two algorithm is no longer that secure as compared to the older days. On Wednesday, February 16, 2005 SHA-1 has been broken by three china research. Although its more towards collision attack rather than pre-image one we can assure one thing is that SHA-1 can be broken and its weaker than we thought. You can read more about it on Bruce Schneier article. On the other hand, you can find MANY MD5 cracker online nowadays through Google. eg. md5crack.com. But similarly they are all collision attacks or rainbow table. Wiki explains MD5 vulnerability in a way you will discourage using it. Its time to encrypt your users password using SHA-2 such as sha256, sha384, sha512 or better.

Hashing your password

If you are using PHP 5.12 or above, there is a new function, hash that supports SHA-2.

$phrase = 'This is my password';
$sha1a =  base64_encode(sha1($phrase));
$sha1b =  hash(’sha1′,$phrase);
$sha256= hash(’sha256′,$phrase);
$sha384= hash(’sha384′,$phrase);
$sha512= hash(’sha512′,$phrase);

For people who are using PHP 5.12 and below, you can try to use mhash which is an open source class for PHP.

$phrase = 'This is my password';
$sha1a =  base64_encode(sha1($phrase));
$sha1b =  base64_encode(bin2hex(mhash(MHASH_SHA1,$phrase)));
$sha256= base64_encode(bin2hex(mhash(MHASH_SHA256,$phrase)));
$sha384= base64_encode(bin2hex(mhash(MHASH_SHA384,$phrase)));
$sha512= base64_encode(bin2hex(mhash(MHASH_SHA512,$phrase)));

SHA-2 should be used to secure your future application. However MD5 and SHA-1 can still be use for authentication purpose with a very secure password combination. eg. ([email protected]#Eif2dsa!e2cX2?"}23{[email protected]

NOTE**: NEVER DOUBLE HASH!

Double hashing is *worse* security than a regular hash. What you’re actually doing is taking some input $passwd, converting it to a string of exactly 32 characters containing only the characters [0-9][A-F], and then hashing *that*. You have just *greatly* increased the odds of a hash collision (ie. the odds that I can guess a phrase that will hash to the same value as your password).

sha1(md5($pass)) makes even less sense, since you’re feeding in 128-bits of information to generate a 256-bit hash, so 50% of the resulting data is redundant. You have not increased security at all.

Credit goes to Ghogilee

****updated on 8 Oct 09

On the note of Ghogilee, i found a few errors which i would like to point out. Double hashing here is referring to two different hash function.  It does reduce the search space but doesn't *greatly* increased the odds of a hash collision.  On the other hand, SHA-1 should be a 160-bit hash not 256-bit and not only does this doesn't increased the security but also weaken the hash function as the hacker will only required to crack the weaker hash function in this case md5.

If you wish to understand the risk and stuff you can do with hash function, please visit Enhance Security Hash Function For Web Development. Here i document the most detail hash function i could for your information.

Enhance Hashing With Salt

Once you have decide your secure password encryption algorithm, the last thing you might want is to have different user having the same cryptographic hash code in order to defend against rainbow attack. This can bring another problem of more than one account being compromised at the same time when there are multiple same hash and short password can easily be cracked with ease when your database and tables have been known. We can generate a salt in order to overcome this problem so that the string is longer and more random (providing that the salt + password are random enough).

define('SALT_LENGTH', 15);
function HashMe($phrase, &$salt = null)
{
$key = '[email protected]#$%^&*()_+=-{}][;";/?<>.,';
    if ($salt == '')
    {
        $salt = substr(hash('sha512',uniqid(rand(), true).$key.microtime()), 0, SALT_LENGTH);
    }
    else
    {
        $salt = substr($salt, 0, SALT_LENGTH);
    }

    return hash('sha512',$salt . $key .  $phrase);
}

The above function contains two parameter. The first will take in a phrase and generate a SHA-2 salt only if the second parameter is placed with an empty variable. However, if both parameter contains values, it will be used when you wish to compare between two hashes. We can use the above method this way,

$username = cleanMe($_POST('username'));
$password = cleanMe($_POST('password'));
$salt = '';
$hashed_password = HashMe($password, $salt);
$sqlquery = 'INSERT INTO  `usertable` ("username", "password", "salt") VALUES  ("'.$username.'", "'.$hashed_password .'", "'.$salt.'") WHERE 1';
..

The above will insert the information into the table when user is being created. We will check the user with the following salt.

$username = cleanMe($_POST('username'));
$password = cleanMe($_POST('password'));
$salt = '';
$sqlquery = 'SELECT `salt`, `password` FROM  `usertable` WHERE `username` = "'.$username.'" limit 1';
..
#we get the data here and placed into variable $row
$salt = $row['salt'];
$hashed_password = HashMe($password, $salt);
if($hashed_password  == $row['password']){
#verified
}
else{
#ACCESS DENIAL
}
..

The objective of salt is to lengthen the password in the table and also creates totally random hash code for each password. Furthermore, a key is being placed in as hash value to protect the password as our SALT is placed in the table and if our table is compromised, the SALT will also be take into consideration in a rainbow table. Therefore, an additional key is required that is not placed within the table. This way, even if your table is being compromised, it will really takes a lot of time for them to crack those hashed password. As i mention earlier, database can be easily compromised due to employee or social engineering.

Summary

Many of us should start moving forward to new hash function rather than sticking on to MD5 and SHA-1. Although it is still secure for these two algorithm to be used given a strong password. Nonetheless, in the near future these two might not be that secure anymore. Furthermore, both algorithm had already been dropped by US and focus on SHA-2 instead. On the other hand, SALT can really help in many ways against social engineering and inside job attack. Its not all about Session attack, SQL Injection, XSS or XRSF nowadays.

WordPress Plugin Development Tips And Tricks

I have been developing WordPress plugin for a while now and it seems like there are always some correct and better ways of writing a particular code in WordPress than mindlessly trying to substitute it with pure PHP. However, these WordPress codes can only be found through countless reading and analyzing of codes from other WordPress sources. In this article, i will present as many tips and tricks i have seen in WordPress that can be very useful for wordpress plugin development.

Find Plugin Directory and URL With WordPress

Previously, i used to hard code the directory by using PHP function. However, after realize there is a better alternative in WordPress, i changed the way i find the plugin directory and URL.

In PHP,

$url = get_bloginfo('url')."/wp-content/plugins/plugin-name/images/hello.jpg";
$directory = dirname(__FILE__)."/plugin-name/images/hello.jpg";

Note: Using dirname(__FILE__) might not always end up on the plugin folder.

In WordPress,

$url = WP_PLUGIN_URL."/plugin-name/images/hello.jpg";
$directory = WP_PLUGIN_DIR."/plugin-name/images/hello.jpg";

Import CSS or JavaScript in WordPress

We love to code these import statement out to the function that performed the action. It can be on the admin page, write post page, home page, etc. But the correct way is to use WordPress action hook and built-in method.

Import CSS/JavaScript to Admin page

function hpt_loadcss()
{
	wp_enqueue_style('hpt_ini', WP_PLUGIN_URL.'/hungred-post-thumbnail/css/hpt_ini.css');
}
function hpt_loadjs()
{
	wp_enqueue_script('jquery');
	wp_enqueue_script('hpt_ini', WP_PLUGIN_URL.'/hungred-post-thumbnail/js/hpt_ini.js');
}
add_action('admin_print_scripts', 'hpt_loadjs');
add_action('admin_print_styles', 'hpt_loadcss');

Import to theme page

function ham_add_style()
{
	$style = WP_PLUGIN_URL . '/hungred-ads-manager/css/ham_template.css';
	$location = WP_PLUGIN_DIR . '/hungred-ads-manager/css/ham_template.css';
	if ( file_exists($location) ) {
		wp_register_style('template', $style);
		wp_enqueue_style( 'template');
	}
}
add_action('wp_print_styles', 'ham_add_style');

Both ways utilize the wp_enqueue_style/wp_enqeue_script method and action hook to import stylesheet and JavaScript properly into WordPress.

Separate Plugin Admin Code

This is only necessary if you are building a large plugin for WordPress. It is efficient to separate the admin codes from others by placing it on an external file so that the admin codes will not be complied by PHP when non-admin user or visitors are accessing your website.

if (is_admin())
include(‘admin.php’);

Secure your WordPress Query

Security something important for all of us. WordPress has a function escape() in their global variable $wpdb. It is best to use this for all data query in your WordPress to better secure your SQL query with the database to prevent any form of security attack. below shows an example,

 $welcome_name = "Mr. WordPress";
  $welcome_text = "Congratulations, you just completed the installation!";

  $insert = "INSERT INTO " . $table_name .
            " (time, name, text) " .
            "VALUES ('" . time() . "','" . $wpdb->escape($welcome_name) . "','" . $wpdb->escape($welcome_text) . "')";

  $results = $wpdb->query( $insert );

You may want to visit the presentation slide that have some interesting WordPress function used for securitySecure Coding with WordPress – WordCamp SF 2008 Slides

Use WordPress For Table Prefix

Never hard code your table prefix in WordPress! WordPress provides a variable in its global variable $wpdb that allows you to easily retrieve your table prefix.

global $wpdb;
$table_name = $wpdb->prefix . "liveshoutbox";

Get Absolute Path In WordPress

In WordPress, you can get the absolute path through the constant ABSPATH which is defined in WordPress.

require_once( ABSPATH . '/wp-includes/classes.php' );
require_once( ABSPATH . '/wp-includes/functions.php' );
require_once( ABSPATH . '/wp-includes/plugin.php' );

Determine Whether a Table Exist In WordPress

Wonder how to determine whether a table exist in your WordPress? You can use the following method to detect whether a particular table exist.

global $wpdb;
$table_name = $wpdb->prefix . "mytable";
if($wpdb->get_var("show tables like '$table_name'") == $table_name) {
	echo 'table exist!';
}

Always Record Table Version

This is an important tips. Always remember to record the version of your plugin table, so you can use that information later if you need to update the table structure. This can help in upgrading your table structure of the plugin in the future.

add_option("hungred_db_version", "1.0");

Create Table Using WordPress Method

This is important for many WordPress developers out there. Although we can create a table using the following method,

	$table = $wpdb->prefix."ham_form";
    $structure = "CREATE TABLE  `".$table."` (
		ham_id DOUBLE NOT NULL DEFAULT 1,
		ham_textarea longtext NOT NULL,
		ham_display longtext NOT NULL,
		UNIQUE KEY id (ham_id)
    );";
    $wpdb->query($structure);

Great! A table is created! Now, tell me how are you going to change this structure in the future? A better alternative is to use the function dbDelta in WordPress.

	$table = $wpdb->prefix."ham_form";
    $structure = "CREATE TABLE  `".$table."` (
		ham_id DOUBLE NOT NULL DEFAULT 1,
		ham_textarea longtext NOT NULL,
		ham_display longtext NOT NULL,
		UNIQUE KEY id (ham_id)
    );";
	require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
	dbDelta($structure);

Directly from WordPress,

The dbDelta function examines the current table structure, compares it to the desired table structure, and either adds or modifies the table as necessary, so it can be very handy for updates (see wp-admin/upgrade-schema.php for more examples of how to use dbDelta). Note that the dbDelta function is rather picky, however. For instance:

* You have to put each field on its own line in your SQL statement.
* You have to have two spaces between the words PRIMARY KEY and the definition of your primary key.
* You must use the key word KEY rather than its synonym INDEX

Hence, any update on the structure of the table will result in a change on the user plugin as well.

Use Nonces During Form Submission

Nonces are used as a security related protection to prevent attacks and mistakes. You can use Nonces to enhance your WordPress form. here is an example,

<form ...>
<?php
if ( function_exists('wp_nonce_field') )
	wp_nonce_field('hungred-post-form'+$uniqueobj);
?>
</form>

We are just using the method wp_nonce_field in WordPress to create a nonce field on the above example. Next, we will need to validate whether the nonce is valid by using the following method after the user have submitted the form. This should be placed before any action began.

<?php check_admin_referer('hungred-post-form'+$uniqueobj); ?>

Pretty easy for enhancing form in your WordPress plugin. But this is not all you can do. There is also Link nonce protection where link is attached with a Nonces. You can read more about Nonces from the below link.

They have better explanation and example to understand Nonce.

Speed up your WordPress plugin development with Ubiquity Firefox add-on

ubiquity

Ubiquity is a Mozilla Firefox add-on, developed by Mozilla Labs. It allows you to search WordPress and PHP (PHP) documentation in an instant. Safe time on Google, more time on development 😀

The Predefined Prototype Object In JavaScript

Most of us learn JavaScript from tutorial website such as w3schools or tizag.com. However, these tutorial site only covered the most fundamental of JavaScript. Many hidden features of JavaScript are usual removed to simplify the tutorial. Although basic does bring us a long way, we still need to read more of these features eventually and improve our coding. In this article, i will cover the predefined prototype object in JavaScript. We will discuss everything we need to know about prototype object and the application in the real world.

The Prototype Object

The prototype object was introduced on JavaScript 1.1 onwards to simplify the process of adding or extending custom properties and methods to ALL instances of an object. In other word, prototype object is used to add or extend object properties or methods so every other object will also have such properties/methods. Let me show you an example. Below listed a few way to extend an object properties.

//adding a custom property to a prebuilt object
var imgObj =new Image();
imgObj.defaultHeight= "150px";

//adding a custom property to the custom object "Shape"
function Shape(){
}
var rectangle =new Shape()
rectangle.defaultColor = 'blue';

From the above example, we are able to extend properties of each object easily. However, if i create a new instances of the same object, the properties will be lost!

var newImg =new Image();
alert(newImg.defaultHeight); //return undefined 'defaultHeight';

var newRec =new Shape()
alert(newRec.defaultColor); //return undefined 'defaultColor';

This is when prototype object comes in. Prototype object is able to add the properties above and extend to other new instances object as well. Hence, the following will allowed all new instances created to contain the properties or methods attached by any previous object. We just have to add the keyword prototype between the object and name of the properties/method to use the prototype object. Using the same example above,

//adding a custom property to a prebuilt object
function check_height(){
 return typeof this.defaultHeight != 'undefined'?true:false;
}
var imgObj =new Image();
imgObj.prototype.defaultHeight= "150px";
imgObj.prototype.hasHeight= check_height;

//adding a custom property to the custom object "Shape"
function Shape(){
}
function color_checker(){
 return typeof this.defaultColor != 'undefined'?true:false;
}
var rectangle =new Shape()
rectangle.prototype.defaultColor = 'blue';
rectangle.prototype.hasColor = color_checker;

var newShape =new Shape()
alert(newShape.defaultColor) // blue
alert(newShape.hasHeight) // true

var newImg =new Image()
alert(newImg.defaultHeight) // 150px
alert(newImg.hasColor()) // true

Now every new instances of Image and Shape will have the properties and methods defined previously by the variables rectangle and imgObj.

Prototype Object Restriction

Prototype object can add or extend properties or methods to any custom object but for predefined object, only those that are created with the new keyword are allowed to use the prototype object in JavaScript. The following list some of these predefined object.

  • The date object
  • The string object
  • The Array object
  • The image object

Prototype Object is an Array

In case you haven't notice, prototype object is actually an array. From all of the above example, we are doing the following declaration to create new properties or method

//declare a function
obj.prototype.name = function(){};
//declare a property
obj.prototype.name = variables;

Notice that we are actually associating a name with a variable or function into the prototype object. Hence, we can also declare prototype with the same way as declaring an array.

obj.prototype ={
name: variables,
name: function(){}
}

The above two methods are similar and can be declare either way. Since both ways are similar, performance wise shouldn't make any big differences.

Priority Between Prototype And Own Property

What if we have both property? If the object itself already has a prototype property and if we redeclare the exact same property again without the keyword prototype, JavaScript will take which property? The answer is own property. In JavaScript, the own property takes precedence over the prototype's. Consider the following example,

function Rectangle(w,h){
	this.area = w*h;
}
var obj = new Rectangle(2,2); //area is 4;
obj.prototype.area = 200; // now we have own and prototype 'area'
alert(obj.area); // 4 will appear instead of 200; Hence, own property takes priority first.

What happened if we delete the property?

delete obj.area
alert(obj.area); // 200 appeared! 

Prototype property will take over again. Hence, we can use the Own property to overwrite prototype property defined in the object.

Identify Own and Prototype Properties

How do we identify whether the given object properties are from own or prototype? In JavaScript, there is a method hasOwnProperty which can be used to identify whether a given property is from own or prototype. Let's look at the following example,

function Rectangle(w,h){
	this.area = w*h;
	this.parameter = w+h;
}
obj.prototype.height = 5; 
obj.prototype.weight = 6; 

var obj = new Rectangle(2,2); 
obj.hasOwnProperty('area');// return true;
obj.hasOwnProperty('parameter');// return true;
obj.hasOwnProperty('height');// return false;
obj.hasOwnProperty('weight');// return false;

Inheritance Using Prototype Object

In the real world, prototype object is usually used as inheritance during OOP (Object Oriented Principle) with JavaScript. In JavaScript, we are not looking at classes inheriting other classes but object inheriting other object since everything in JavaScript is Object. Once we understand this, it will be easier for us to show inheritance example with prototype object.

function Shape(){
}
function color_checker(){
 return typeof this.defaultColor != 'undefined'?true:false;
}
function getArea(){
return this.area;
}

Shape.prototype.defaultColor = 'blue';
Shape.prototype.hasColor = color_checker;
Shape.prototype.getArea = getArea;

function Rectangle(w,h)
{
	this.area = w*h;
}

function Rectangle_getArea()
{
    alert( 'Rectangle area is = '+this.area );
}
Rectangle.prototype = new Shape();
Rectangle.prototype.constructor = Rectangle;
Rectangle.prototype.getArea  = Rectangle_getArea; 

Using the custom object 'Shape' example above, i extend it so that 'Rectangle' will inherit all method and properties of 'Shape'. Inherit can be done through this sentence

Rectangle.prototype = new Shape();

'Rectangle' prototypes are assigned to the prototype of the 'Shape' through an object instance thereby "inheriting" the methods assigned to the prototype array of 'Shape'. After 'Rectangle' has inherit 'Shape', it overwrites the getArea method of 'Shape' through this statement.

Rectangle.prototype. getArea  = Rectangle_getArea; 

Inheritance using prototype object can reduce a lot of unnecessary coding and make your overall code run faster. The constructor on the above code is to overwrite the way Rectangle object is being instantaneous since the Rectangle prototype was overwritten by Shape prototype on the previous statement. Hence, to create a Rectangle object, the constructor for it will be as follow

function Rectangle(w,h)

We can use the above code as follow

var recObj = new Rectangle(20, 20);
rec.getArea(); //return 'Rectangle area is = 400'
rec.hasColor(); // return true;
rec.defaultColor;//return blue;

Check Prototype Inheritance

We can check whether a particular object is another prototype object by using the function isPrototypeOf. In other word, we can check whether a particular object inherit another object properties and methods. Using the previous inheritance explanation, we can check whether Shape is inherited into Rectangle object.

var rec = new Rectangle(5,5);
Shape.isPrototypeOf(rec);// return true;

This shows that Shape is a prototype of rec object. I think the method name said it all.

Solutions To Session Attacks

Recently i wrote two other security article on XSS and SQL Injection. I find many interesting facts and solutions on those topic that i research about and wanted to know more about other security measure. Thus, in this article i will discuss on different type of session attacks and how we can better protect ourselves against these attacks to better secure our web portal.

Session attack is nothing more than session hijacking. The most important information in session attack is to obtain a valid valid session identifier (SID). There are three common methods used to obtain a valid session identifier.

  • Session Prediction
  • Session Capture
  • Session Fixation

Session Prediction

Prediction refers to guessing a valid session identifier. With PHP's native session mechanism, the session identifier is extremely random. Hence, it is difficult to guess such SID. Although it is not the weakest point of a secure website. There are still chances of accessing the site through this method.

Solution To Session Prediction

Use of a longer random number or string as the session key. This reduces the risk that an attacker could simply guess a valid session key through trial and error or brute force attacks.

Session Capture

Capturing a valid session identifier is the most common type of session attack. Rather than predicting a correct session identifier is much easier. This approach is also known as Session Sidejacking, where the attacker uses packet sniffing to read network traffic between two parties to steal the session cookie. Unsecured Wi-Fi hotspots are particularly vulnerable, as anyone sharing the network will generally be able to read most of the web traffic between other nodes and the access point.

Solution To Session Capture

Encryption of the data passed between the parties; in particular the session key. This technique is widely relied-upon by web-based banks and other e-commerce services, because it completely prevents sniffing-style attacks. However, it could still be possible to perform some other kind of session hijack. Many web application apply SSL only on login page where session id can still be sniff out on subsequence pages. The password of such application is protected but not the session.

Session Fixation

Session fixation attacks attempt to exploit the vulnerability of a system which allows one person to fixate another person's session identifier (SID). Most session fixation rely on session identifiers being accepted from URLs (query string) or POST data.

Scenario Of Session Fixation Attacks

Here are some ways session fixation can be launched.

Simple Attack

The most simple way of an attack that can be launched due to website vulnerability.

  1. Attacker A knows http://unsafe.com is an unsafe site that accept SID directly through query string and no validation is being done on the site.
  2. Attack A send an email to Victim B 'Someone tried to access your bank account. Please access your account at http://unsafe.com?SID=H2SK9XSU1fL197DQ621Sh to change your password.' Attacker A is trying to fixate the SID to H2SK9XSU1fL197DQ621Sh.
  3. Victim B clicked on the URL provided and was bought to the login site.
  4. Victim B logged in with his access and tried to verify.
  5. Attack A then used the same URL to gain Victim B access since the session has been fixed to H2SK9XSU1fL197DQ621Sh.

Server Generated SID Attack

Misconcept of server generated session identifier is safe from fixate. Unfortunately not.

  1. Attacker A visits http://unsafe.com/ and checks which SID is returned. For example, the server may respond: Set-Cookie: SID=9AS82120DK8E0DI.
  2. Attacker A send in an email to Victim B. 'Please join our latest promotion at 'http://unsafe.com?SID=9AS82120DK8E0DI'.
  3. Victim B logged in and caused the fixate on 9AS82120DK8E0DI. Finally, Attacker A enters the same URL to gain unauthorizes access.
  4. Typically the same way as simple attack. The only differences is that the session identifier is being created by the server instead of the unsecured one.

Cross-Site Cooking Attack

Cross-site cooking is a type of browser exploit which allows a site attacker to set a cookie for a browser into the cookie domain of another site server. It exploits browser vulnerabilities although the original site was secure.

  1. Attacker A sends Victim B an e-mail: "Hey, celina has recommend you a new site at http://unsafe.com/"
  2. Victim B visits http://unsafe.com/, which sets the cookie SID with the value H2SK9XSU1fL197DQ621Sh into the domain of http://safe.com/
  3. Victim B then receives an e-mail from Attacker A, "Due to new implementation we will required you to login to http://safe.com/ to verify your bank account".
  4. Once Victim B logs on, Attacker A can use her account using the fixated session identifier.

Cross-Subdomain Cooking Attack

This is the same thing as cross site cooking, except that it does not rely on browser vulnerabilities. Rather, it relies on the fact that wildcard cookies can be set by one subdomain that affect other subdomains.

  1. A web site such as www.blogprovider.com hands out subdomains to untrusted third parties
  2. Attacker A who controls evil. blogprovider.com, lures Victim B to his site
  3. A visit to evil.blogprovider.com sets a session cookie with the domain .blogprovider.com on Victim's B browser
  4. When Victim B visits www.blogprovider.com, this cookie will be sent with the request, as the specs for cookies states, and Victim B will have the session specified by Attacker A cookie.
  5. If Victim B now logs on, Attacker A can use her account.

Victim B can be a administrator on blogprovider.com/administrator.

Each session attack scenario has resulted in Privilege escalation or Cross-calation which exploit a bug or flaw in the system to gain unauthorizes access. Such attacks are dangerous as Attack A can spy on Victim B on whatever he is doing on the system. If Victim B decides to purchase something on this site and enters her credit card details, Attack A may be able to harvest Victim B history access to see such sensitive data and details.

Session Fixation Attack

In order to better illustrate session fixate, we will consider the following example,

<?php
session_start();
if (!isset($_SESSION['visits']))
{
	$_SESSION['visits'] = 1;
}
else
{
	$_SESSION['visits']++;
}
echo $_SESSION['visits'];
?>

The above state that every different browser or new cookie session should have a start index of '1'. To demonstrate session fixation, first make sure that you do not have an existing session identifier, then visit this page with domain.com?PHPSESSID=1234. Next, with a completely different browser (or even a completely different computer), visit the same URL again with domain.com?PHPSESSID=1234. You will notice that the output show 2 instead of 1 because the session was continue! This is session fixate where the same session is used to continue previous session although you were not the first initializer.

Solutions To Session Fixation Attacks

Although Session Fixation is widely used. There are also many solutions for such attacks.

Do not accept session identifiers from GET / POST variables

We know from XSS attack article that global variable is dangerous. Session Fixation is one of the live example of such danger. We are all aware from this article that session fixation is achieve through query string or POST variable. Thus, prevent using such method for SID one of the best solution you can undertake to prevent simplify attack.

Additionally, such usage also increase the risk of:

  1. SID is leaked to others servers through the Referrer
  2. SID is leaked to other people through communication channels and social network
  3. SID is being stored in many places (browser history log, web server log, proxy logs, ...)

Change Important Session identifier

Session Fixation can be largely avoided by changing the session ID when users log in. In every important event, changing the session identifier will prevent attackers from accessing these important event. When the victim visits the link with the fixed session id, however, they will need to log into their account in order to do anything "important" as themselves. At this point, their session id will change and the attacker will not be able to do anything "important".

Store session identifiers in HTTP cookies

The session identifier on most modern systems is stored by default in an HTTP cookie, which has a moderate level of security. However, modern systems often accept session identifiers from GET/POST as well. The web server configuration must be modified to protect against this vulnerability.

; Whether to use cookies.
session.use_cookies = 1

; This option enables administrators to make their users invulnerable to
; attacks which involve passing session ids in URLs; defaults to 0.
session.use_only_cookies = 1

Utilize SSL / TLS Session identifier

When enabling HTTPS security, some systems allow applications to obtain the SSL / TLS session identifier. Use of the SSL/TLS session identifier is very secure, but many web development languages do not provide robust built-in functionality for this.
SSL/TLS session identifiers may be suitable only for critical applications, such as those on large financial sites, due to the size of the systems. This issue, however, is rarely debated even in security forums.

Regenerate SID on each request

Similar to 'Change Important Session identifier', however, this will regenerate the session identifier every single time a page is being request. This will further enhance the security since every single request by the user will eventually change the session identifier. Even if someone were able to capture session identifier through sniffing, the session id will eventually change which will make attacks difficult.

Accept only server generated SIDs

One way to improve security is not to accept session identifiers that were not generated by the server. Making life difficult for attacker is also one of the most important way of improve security.

#remove any session that may exist
if (!isset($_SESSION['SERVER_GENERATED_SID'])) {
   session_destroy(); 
}
#generate a new session id through built-in function
session_regenerate_id(); 
$_SESSION['SERVER_GENERATED_SID'] = true;

Logout function

Session Fixation will only be active when the known session identifier is the same. Thus, the attacker known session identifier will be invalid when the user logout themselves. Hence, having the following function is critical to improve session security.

if (isset($_POST['LOGOUT']))
   session_destroy(); // destroy all data in session

Time-out Session Identifier

Another very critical process of securing a web application is to implement a time out function to destroy the session whenever a session has expired. A session will expired after a given time. This defense is simple to implement and has the advantage of providing a measure of protection against unauthorized users accessing an authorized user's account by using a machine that may have been left unattended.

Store a session variable containing a time stamp of the last access made by that SID. When that SID is used again, compare the current timestamp with the one stored in the session. If the difference is greater than a predefined number, say 5 minutes, destroy the session. Otherwise, update the session variable with the current timestamp.

Destroy session if Referrer is suspicious

As mention on the scenario of session fixation, cross site cooking required an access to a bad URL and set the cookie session to the real URL. Destorying the session will prevent such attack from happening.

#check whether the referer is from our domain.
if (strpos($_SERVER['HTTP_REFERER'], 'http://mywebsite.com/') !== 0) {
   session_destroy(); // destroy all data in session
}
session_regenerate_id(); // generate a new session identifier

Verify IP

One way to further improve security is to ensure that the user appears to be the same end user (client). This makes it a bit harder to perform session fixation and other attacks. As more and more networks begin to conform to RFC 3704 and other anti-spoofing practices, the IP address becomes more reliable as a "same source" identifier. Therefore, the security of a web site can be improved by verifying that the source IP is consistent throughout a session.

if($_SERVER['REMOTE_ADDR'] != $_SESSION['PREV_REMOTEADDR']) {
   session_destroy(); // destroy all data in session
}
session_regenerate_id(); // generate a new session identifier
$_SESSION['PREV_REMOTEADDR'] = $_SERVER['REMOTE_ADDR'];

However, there are some points to consider before employing this approach.

  • Several users may share one IP. It is not uncommon for an entire building to share one IP using NAT.
  • Inconsistent IP as the users are behind proxies (such as AOL customers) or from mobile/roaming.

User Agent

Although the attacker may be able to change the user agent to match the one on the session. However, it makes the process even more difficult and may help prevent some attacker from penetrating through the session. A web application might make use of User-Agent detection in attempt to prevent malicious users from stealing sessions.

#check whether the stored agent is similar to user agent
if ($_SERVER['HTTP_USER_AGENT'] !== $_SESSION['PREV_USERAGENT']) {
   session_destroy(); // destroy all data in session
}
session_regenerate_id(); // generate a new session identifier
$_SESSION['PREV_USERAGENT'] = $_SERVER['HTTP_USER_AGENT'];

Full Defense

Creating multiple layer of defense mention above into a fully functional method to be used in every session authentication.

function validate_session($url)
{
	if (strpos($_SERVER['HTTP_REFERER'], $url) !== 0 ||
		isset($_GET['LOGOUT']) ||
		$_SERVER['REMOTE_ADDR'] !== $_SESSION['PREV_REMOTEADDR'] ||
		$_SERVER['HTTP_USER_AGENT'] !== $_SESSION['PREV_USERAGENT'])
	  session_destroy();
    #time-out logic

	session_regenerate_id(); // generate a new session identifier

	$_SESSION['PREV_USERAGENT'] = $_SERVER['HTTP_USER_AGENT'];
	$_SESSION['PREV_REMOTEADDR'] = $_SERVER['REMOTE_ADDR'];
}

Other Attacks

Cross-site scripting, where the attacker tricks the user's computer into running code or link which is treated as trustworthy because it appears to belong to the server, allowing the attacker to obtain a copy of the cookie or perform other operations.

Alternatively, an attacker with physical access can simply attempt to steal the session key by, for example, obtaining the file or memory contents of the appropriate part of either the user's computer or the server.

Summary

Session attacks are common among the attack used on secure website. Effort has to be made to improve session security to prevent any thief from happening. The solutions above might not be full bullet proof solution for future session attacks. Nonetheless, it can be used for discussion on solutions of future such attack.