Hardening Website Security – Part 2: User Session Cookie Security

Introduction

It feels like almost every week there’s another news item about personal information being stolen because yet another company’s website got hacked.

Most of these attacks are perpetrated through social engineering, persuading somebody to hand over some detail which allows the hacker to gain additional privileges and, eventually, access to personal information. However, a lot are still carried out due to poor security or misconfigured websites.

This is the second in a series of articles which will aim to demystify some of the concepts you must get your head around if you hope to run a secure website in the 21st century.

Contents

The series will be consist of the following topics:

  1. HTTP Security Headers
    o 1a. HSTS Preloading
  2. User Session Security
  3. Database Security
  4. Safely Handling User Input

Topics Not Covered

I have opted not to cover server infrastructure security concerns at this time due to the huge number of possible configurations (hosting packages or VPS, operating systems, dashboard systems, firewalls, etc.) While I may cover some of these specifically in future articles, there’s too much nuance in these subjects to be able to do them justice here.

Disclaimer

Everything presented in this article is the result of years of experience, or trial and (frequent) error. Messing around with the code and/or settings on a live site can (and likely will) lead to unexpected, possibly disastrous results. The information presented here is correct to the best of the author’s knowledge, but in matters of security we strictly advise the reader to make sure they carry out additional research and understand the dangers before making any changes to their own systems or web sites. Any code presented here is done so as example only, and may be incomplete or contain errors. Readers should be careful when copying and pasting code from any website, this site included. Int64 Software Ltd, its employees and its representatives accept no liability for damage caused by the misuse, either intentional or unintentional, of the information presented in its posts and articles.

Section Overview

In this section we will be looking at how you can increase the security of user sessions on your web server, and reduce the risk of Session Hijack Attacks.

Dynamic websites will typically make use of Sessions in order to store data for each user to facilitate the logic behind things like user logins, or shopping carts. All session data is stored securely on the web server except for a single cookie which identifies that user and associates them with their session data.

On an unsecured website, if an attacker is able to capture this session cookie (which can be done many different ways such as packet sniffing, Cross Site Scripting attacks (XSS), or just looking over the person’s shoulder), they could manually add that to their own web browser and effectively “hijack” that user’s session, gaining access to their data. We aim to look at the ways that this can be prevented by utilising a few simple settings and techniques.

Overcee - Delegated Device Management System for Windows Service Desks

Session Settings

Session Name

The session name is the name of the cookie that is set on the client’s web browser. The value of this cookie will be a unique, randomly generated string which identifies the user, but the name is important as well.

By default, the cookie name used by web server software is predictable and descriptive, such as “PHPSESSID” for PHP, or “ASP.NET_SessionId” for ASP.NET. This means that if an attacker is trying to steal this cookie’s value, it is very easy for them to identify the correct cookie.

For this reason, it is recommended that the session name is set to something incredibly generic so that it may be overlooked, such as just “id”.

PHP

Before calling “session_start();”, call the “session_name” method to set your session cookie name:

session_name(‘id’);

ASP.NET

Specify the “cookieName” attribute in your sessionState property of the web.config file:

<sessionState cookieName=”id”></sessionState>

Only Use Cookies

Many web servers offer the ability to automatically attach the session ID to the end of any POST or GET requests. The reason for this is that it allows for sessions to still be used even if the user has disabled cookies in their browser.

However, this presents three problems:

  1. An attacker can easily identify and read this value, which could lead to Session Hijack attacks.
  2. It is possible an attacker could, having got this value, send a crafted URI back to the user which could carry an unintended action on the website using the user’s session information. This is known as a Cross-Site Request Forgery attack (covered in Part 4 of this series).
  3. If you make use of scripted Ajax calls, you may have to remember to manually append the session ID to each request.

For these reasons, it is recommended that this option is disabled.

PHP

Note that since PHP 5.3.0 this is disabled by default. However, if you want to ensure it is disabled then check the “php.ini” file for the following settings.

session.use_only_cookies = 1
session.use_trans_sid = 0

Alternatively, before sending any output to the client you can change this in your PHP files with the command:

ini_set(‘session.use_only_cookies’, true);
ini_set(‘session.use_trans_sid’, false);

ASP.NET

It is a little harder to restrict this in ASP.NET which calls it “cookieless”. First you need to set the sessionState to disable cookieless mode in your web.config:

<sessionState cookieless=”UseCookies”></sessionState>

The, also in your web.config file, set any login forms to not use cookieless mode:

<authentication mode=”Forms”>
	<forms loginUrl=”login.aspx” cookieless=”UseCookies” requireSSL=”true” path=”/MyApplication” />
</authentication>

Next, also in “web.config“, set “anonymousIdentification” to disable cookieless (Note that I haven’t included all of the other anonymousIdentification settings here for the sake of brevity):

<anonymousIdentification cookieless=”UseCookies” /> 

Finally, you need to catch requests from clients which have cookies disabled and handle them. This script will simply block the request, but you may want to redirect them instead:

If(Request.Browser.Cookies == false)
{
	Response.Close();
}

Strict Mode

By default in PHP, if a client sends the server a session ID that it doesn’t recognise for that client, it will create a new session using that ID. This can lead to Session Fixation Attack where the attacker uses the ID of another user’s session to hijack their session.

To combat this, Strict Mode should be enabled. By doing this, if PHP receives an uninitialized session ID, it will generate a new ID and send that back to the client.

To enable this mode, in “php.ini” make sure the following is set:

session.use_strict_mode = 1

Alternative, in your PHP files you can set this with the command:

ini_set(‘session.user_strict_mode’, true);

I was unable to find a single solid answer in my research as to whether this is a problem in ASP.NET as well, or what the fix is if it is. If anyone knows, please drop me an email.

Session Cookie Options

Lifetime

The session cookie should be given a suitably short lifetime value so that if the user idles for a time, then they must, for example, re-authenticate when returning to your website.

Many web servers do this by default, and limit it to 30 minutes or below.

Secure

By setting the “Secure” attribute on the session cookie, web browsers are instructed to only send the cookie over encrypted HTTPS channels. Failing to set this can mean that the cookie could be captured or modified through a Man-in-the-Middle attack.

Note that this is possible even if your web site enforces HTTPS-only communications via HSTS, redirects, or even if no HTTP connection is presented.

HttpOnly

Setting the “HttpOnly” property prevents web scripts (JavaScript, VBScript, etc) from accessing this cookie via the “document.cookie” DOM object, which is important to prevent a Cross Site Scripting (XSS) attack from stealing the session cookie ID.

Regenerating Session ID

In order to limit the amount of time an attacker has to use a stolen session ID to hijack the session, it is necessary to limit the lifespan of a session.
This can be achieved in one of two ways:

  1. The session is timed out and removed from both the client and server, forcing the user to re-enter any stored information (by logging back in, or re-adding items to their shopping cart).
  2. The session is kept active, but the session ID is regenerated with a new random value.

Naturally, from a user experience viewpoint, the latter option is preferable.

In addition to regularly regenerating the session ID, it should also be refreshed on a Security State Change, such as when a user logs in or out, or when they attempt to access sections of website which are deemed more secure than others (such as Administrator functions).

Further Reading

For more information on Session Cookie security, we highly recommend the Open Web Application Security Project’s (OWASP) Session Management Cheat Sheet

What’s Next?

That’s it for this article. Next time we’ll be looking into making sure your Database connection and transactions are kept secure. To continue reading, click here.

Like the article? Share with your friends: