Skip to content
View in the app

A better way to browse. Learn more.

Web Designer Forum

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Sidejacking, and how to stop it

Featured Replies

I posted this on my Facebook for my CompSci friends to see, figured it'd be helpful outside of those 50 or so people.

 

"Sidejacking" is when a hacker uses a packet-sniffer to detect the login auth cookie and uses that cookie data himself to pretend to be authorised on a website.

 

This is possible because mostly what we do to say that a user is authorised is create a unique hash (using sha1 or similar) and store it in both the database and the cookie:

salt = sha1( username + password + time() )
cookie['login'] = salt
database.write( login = salt )

 

Then to check that the user is authorised, we do

if( database.get_where( login = cookie['login'] ) ) ...

 

Sidejacking works because the cookie can be used from any location. How to stop this? Add some user-specific data (IP and user agent) based encryption and store two different hashes like so:

salt = sha1( username + password + time() )
cookie['login'] = salt
database.write( login = sha1( salt + IP + UA ) )

if( database.get_where( login = sha1( cookie['login'] + IP + UA ) ) ...

 

Now a sidejacking attempt can't work because the IP and UA is required to transmute from the cookie salt to the DB salt. Simples :)

 

Note that this won't stop all attacks - the UA is not unique to each user and sidejacking often occurs within the same network (so the IP is shared beyond the router), but it will stop most of the rudimentary attempts when you can't get SSL running throughout the site.

 

(The easiest and most complete method of stopping sidejacking is using SSL (https) encryption for all authorised pages so that cookies/sessions can't be grabbed by a packet sniffer. However, that's not always a possibility due to server or cost restraints.)

I posted this on my Facebook for my CompSci friends to see, figured it'd be helpful outside of those 50 or so people.

 

"Sidejacking" is when a hacker uses a packet-sniffer to detect the login auth cookie and uses that cookie data himself to pretend to be authorised on a website.

 

This is possible because mostly what we do to say that a user is authorised is create a unique hash (using sha1 or similar) and store it in both the database and the cookie:

salt = sha1( username + password + time() )
cookie['login'] = salt
database.write( login = salt )

 

Then to check that the user is authorised, we do

if( database.get_where( login = cookie['login'] ) ) ...

 

Sidejacking works because the cookie can be used from any location. How to stop this? Add some user-specific data (IP and user agent) based encryption and store two different hashes like so:

salt = sha1( username + password + time() )
cookie['login'] = salt
database.write( login = sha1( salt + IP + UA ) )

if( database.get_where( login = sha1( cookie['login'] + IP + UA ) ) ...

 

Now a sidejacking attempt can't work because the IP and UA is required to transmute from the cookie salt to the DB salt. Simples :)

 

Note that this won't stop all attacks - the UA is not unique to each user and sidejacking often occurs within the same network (so the IP is shared beyond the router), but it will stop most of the rudimentary attempts when you can't get SSL running throughout the site.

 

(The easiest and most complete method of stopping sidejacking is using SSL (https) encryption for all authorised pages so that cookies/sessions can't be grabbed by a packet sniffer. However, that's not always a possibility due to server or cost restraints.)

 

This is a very good topic, I hashed the session key that is stored into the cookie or session, then check against it in the database, but your right saying use the users unique data as a backup plan.

Indeed it is worth saying, and said it was in the original post.

 

Yh thanks for posting this, Im working on a login system now and just when i think its fool proof its actualy not.

Yh thanks for posting this, Im working on a login system now and just when i think its fool proof its actualy not.

 

What do you use to test if your code is secure? :)

  • Author

Common sense and experience are my tools - relying on the knowledge of others (either in pure form, or tool form) is also a good route.

 

My latest login code (which I make no claims as to it's perfection) is as follows (in form of a CodeIgniter model, the best framework ever):

function login( $username = false, $password = false )
{
  	// get from object if not passed
	if( ! $username ) $username = $this->username;
	if( ! $password ) $password = $this->password;

  	// create salt
	$salt = sha1( $username.$password.time() );

  	// update database based on username & password
	$this->db->where( "username", $username );
	$this->db->where( "password", sha1( $password ) );
	$this->db->set( "salt", sha1( $salt . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) );
	$this->db->update( "users" );

	// the "it didnae work" bit
	if( ! $this->db->affected_rows() )return false;

   	// if it did work, get the user from the db
	$this->db->where( "username", $username );
	$this->db->where( "password", sha1( $password ) );
	$user = $this->db->get( "users" )->row();

	// backup "no database" failure bit
	if( $user->salt != sha1( $salt . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) ) return false;

	// copy data to object
	foreach( $user as $i=>$v )
		$this->$i = $v;

	$this->parse_settings();

	// set cookie
	set_cookie( "natrium", $salt, 86400 * 30 );

	return true;
}

function get()
{
  	// if user is already set, return self (true)
	if( $this->username && $this->id ) return $this;

  	// unset all variables as backup
	foreach( array( "id", "username", "email", "password", "salt", "name" ) as $k )
		$this->$k = false;

	$this->salt = get_cookie( "natrium" );

  	// get user from db where salt matches rehash
	$this->db->where( "salt", sha1( $this->salt . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) );
	$q = $this->db->get( "users" );

	if( ! $q->num_rows ) return false;

	foreach( $q->row() as $k=>$v ) $this->$k = $v;

	$this->parse_settings();

	return $this;
}

 

btw: natrium is the Latin for sodium, one half of table salt (sodium chloride) and most other salts...

Common sense and experience are my tools - relying on the knowledge of others (either in pure form, or tool form) is also a good route.

 

My latest login code (which I make no claims as to it's perfection) is as follows (in form of a CodeIgniter model, the best framework ever):

function login( $username = false, $password = false )
{
  	// get from object if not passed
	if( ! $username ) $username = $this->username;
	if( ! $password ) $password = $this->password;

  	// create salt
	$salt = sha1( $username.$password.time() );

  	// update database based on username & password
	$this->db->where( "username", $username );
	$this->db->where( "password", sha1( $password ) );
	$this->db->set( "salt", sha1( $salt . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) );
	$this->db->update( "users" );

	// the "it didnae work" bit
	if( ! $this->db->affected_rows() )return false;

   	// if it did work, get the user from the db
	$this->db->where( "username", $username );
	$this->db->where( "password", sha1( $password ) );
	$user = $this->db->get( "users" )->row();

	// backup "no database" failure bit
	if( $user->salt != sha1( $salt . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) ) return false;

	// copy data to object
	foreach( $user as $i=>$v )
		$this->$i = $v;

	$this->parse_settings();

	// set cookie
	set_cookie( "natrium", $salt, 86400 * 30 );

	return true;
}

function get()
{
  	// if user is already set, return self (true)
	if( $this->username && $this->id ) return $this;

  	// unset all variables as backup
	foreach( array( "id", "username", "email", "password", "salt", "name" ) as $k )
		$this->$k = false;

	$this->salt = get_cookie( "natrium" );

  	// get user from db where salt matches rehash
	$this->db->where( "salt", sha1( $this->salt . $_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] ) );
	$q = $this->db->get( "users" );

	if( ! $q->num_rows ) return false;

	foreach( $q->row() as $k=>$v ) $this->$k = $v;

	$this->parse_settings();

	return $this;
}

 

btw: natrium is the Latin for sodium, one half of table salt (sodium chloride) and most other salts...

 

wow this is impressive code!

  • Author

wow this is impressive code!

 

I'm a 3rd year Computer Science student, and have been using PHP since for about 6 years (since I was 15). I've been using CodeIgniter for around 2 years and have created plenty of commercial systems with it... so plenty of experience.

I'm a 3rd year Computer Science student, and have been using PHP since for about 6 years (since I was 15). I've been using CodeIgniter for around 2 years and have created plenty of commercial systems with it... so plenty of experience.

 

CodeIgniter? Ive never used any addons, Ive always written apps from groupup? I could google, but whats it for and how good is it?

  • Author

CodeIgniter is a free OS OOP HMVC framework (wooo acronyms) that prides itself on being:

- lightweight (about 1.3mb memory footprint usually, which is good for it's capabilities),

- extensible (true, but requires decent code skills), and

- allowing minimal code to get things done (again true, again requiring good knowledge to truly exploit)

 

It doesn't force a new microlanguage or meme on you like most frameworks, beyond gently nudging you towards following the MVC pattern.

 

I strongly recommend you try it out for a few weeks - it's cut my code time (creation AND maintenance) dramatically whilst increasing program performance.

CodeIgniter is a free OS OOP HMVC framework (wooo acronyms) that prides itself on being:

- lightweight (about 1.3mb memory footprint usually, which is good for it's capabilities),

- extensible (true, but requires decent code skills), and

- allowing minimal code to get things done (again true, again requiring good knowledge to truly exploit)

 

It doesn't force a new microlanguage or meme on you like most frameworks, beyond gently nudging you towards following the MVC pattern.

 

I strongly recommend you try it out for a few weeks - it's cut my code time (creation AND maintenance) dramatically whilst increasing program performance.

 

Im setting up a blog tonight so i may have a look :) your coding has realy impressed me, its almost asif i carnt read it.

Create an account or sign in to comment

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.