Featured

How to Manage User Sessions in PHP Securely

Despite all the advantages that sessions offer, the disadvantages should not be completely ignored.

 

No Sessions without Cookies!

Especially with cookieless sessions, the discrepancy between convenience and security is huge. It used to be claimed that web applications wouldn't work without cookieless sessions, but nowadays it's more likely that it won't work with cookieless sessions.

 

The reason for this is very simple: the key to all information, the session ID, is in this case in the plain text of the URL. Imagine the following situation: A webmail provider uses cookieless sessions. You send an email to a customer of the webmail provider with a link to your website, or more precisely, with a link to a PHP script. When the mail recipient clicks the link, the script is called up. The first thing you do with the script is look at $_SERVER["HTTP_REFERER"]. Web browsers send the URL of the previous page in this HTTP header field. With minimal effort, you can read this and at the same time determine the customer's current session ID with the webmail provider. This is also

known as session hijacking.

 

When freemail services were just becoming popular, some well-known providers were susceptible to this type of attack. For this reason, all mail providers now use (temporary) cookies to transfer the session ID.

 

There are several countermeasures against session hijacking, but none of them work completely. One potential antidote is to restrict sessions to one IP address. This can be done in several steps:

  1. When creating the session, save the visitor's current IP address in a separate session variable:

   $_SESSION["ip"] = $_SERVER["REMOTE_ADDR"];

  1. Each time the session is accessed, the system checks whether the IP address is still correct. If not, the session is deleted:

if ($_SESSION["ip"] != $_SERVER["REMOTE_ADDR"]) {

   session_unset();

   session_destroy();

   setcookie(session_name(), "away with it", 0, "/");

   }

 

However, this procedure also has a catch. The entry in the $_SERVER ["REMOTE_ADDR"] field is not always reliable, especially if a proxy server is in use. This also harbors dangers:

  • When using a proxy server, all users behind the proxy have the same IP address from the web server's point of view. It is therefore easy to steal a session ID within a company network. Some internet providers are also notorious for using different proxies.
  • The true IP address of the user is in $_SERVER["HTTP_X_FORWARDED_FOR"]—but not always.

There is therefore no 100% perfect way of determining the user's IP address.

 

Check the Referrer

Another approach is to evaluate the HTTP_REFERER environment variable and always check which page the user is coming from. If a session ID is "stolen," the referrer value may be incorrect. Unfortunately, this is not always reliable either, as the referrer is not always sent these days. Nevertheless, if you still want to use this method, PHP makes it very easy for you. The session.referer_check configuration setting can be set to a character string that must always appear in HTTP_REFERER; otherwise, the session will be deleted.

 

Change the Session ID

To further reduce the effects of session hijacking, it can be helpful to limit the validity of a (possibly hijacked) session ID. The session_regenerate_id() function is useful for this. Whenever this is called, PHP generates a "fresh" session ID but copies all data from the existing session to the new version.

 

The session_regenerate_id() function has an optional parameter. If this is set to true, the old session is deleted. In other words, if the session ID is stolen by an attacker, this session is history after the next call to session_regenerate_id().

 

This procedure is also not without its disadvantages. The permanent creation of new session IDs eats up some performance on the server. Apart from that, however, this is a security feature in PHP that is envied by some other web technologies.

 

Note: The article at http://s-prs.co/v602282, which is also linked to from the PHP online manual, provides a good overview of the problem of the "hostile takeover" of sessions.

 

Making Cross-Site Request Forgery More Difficult

A typical attack scenario in the context of CSRF consists of making a cross-domain request and relying on the fact that all cookies from the target domain are then also sent. With SameSite cookies, all current browsers support a mechanism that makes this more difficult by handling cookies with a corresponding SameSite flag more restrictively for requests from another domain. For session cookies, this flag can be set via php.ini configuration:

 

session.cookie_samesite = "Strict"

 

Other possible values are "None" and "Lax".

 

Prevent JavaScript Access to the Session Cookie

Another security feature can protect against the effects of cross-site scripting (XSS): If you set the php.ini configuration option for session.cookie_httponly to 1 or On, then session cookies are marked with the httponly flag. This at least makes session hijacking with JavaScript more difficult.

 

In principle, however, the following applies: Only use sessions with the session ID in a cookie! Over the last 20 years, the authors have repeatedly seen projects in web development that had to work without cookies: obscure clients on handheld devices that did not support cookies, internal web applications used with a browser that was not allowed to accept cookies due to a company-wide policy, and a few other extreme cases. The key word here is extreme as normally there is no excuse for using sessions without cookies. Try it out for yourself: Surf once with cookies disabled and see how far you get—especially with webmail services and online stores.

 

Editor’s note: This post has been adapted from a section of the book PHP and MySQL: The Comprehensive Guide by Christian Wenz and Tobias Hauser. Christian is a consultant and trainer who specializes in web technologies and web security. He leads digitization projects in corporate environments. His books have been translated into more than a dozen languages. Tobias is a consultant, trainer, and author. He supports companies with his focus on PHP-based web applications, covering everything from system selection to interface architecture, and writes regularly about web topics.

 

This post was originally published 3/2025.

Recommendation

PHP and MySQL
PHP and MySQL

Dive into web development with this comprehensive guide to PHP 8! Whether you’re a beginner or an experienced developer, you’ll find everything you need to build dynamic, secure websites. Walk through installing PHP, object-oriented programming, and working with databases like MySQL. Gain hands-on experience with detailed code and application examples. Master advanced topics like debugging, automated testing, security, and more!

Learn More
Rheinwerk Computing
by Rheinwerk Computing

Rheinwerk Computing is an imprint of Rheinwerk Publishing and publishes books by leading experts in the fields of programming, administration, security, analytics, and more.

Comments