The PHP session mechanism is quite simple. Once the session is started using session_start() or the php.ini session.autostart setting, the PHP engine generates a unique token that is, by default, conveyed to the user by way of a cookie. On subsequent requests, while the session is still considered active, the user's browser (or equivalent) presents the session identifier, again usually by way of a cookie, for inspection. The PHP engine then uses this identifier to locate the appropriate file on the server, populating $_SESSION with the stored information. There are tremendous security concerns when the session identifier is the sole means of identifying a returning website visitor. In this recipe, we will present several techniques that will help you to safeguard your sessions, which, in turn, will vastly improve the overall security of the website.
loggedIn flag in $_SESSION:session_start();
$loggedIn = $_SESSION['isLoggedIn'] ?? FALSE;
if (isset($_POST['login'])) {
if ($_POST['username'] == // username lookup
&& $_POST['password'] == // password lookup) {
$loggedIn = TRUE;
$_SESSION['isLoggedIn'] = TRUE;
}
}$_SESSION['isLoggedIn'] is set to TRUE:<br>Secret Info <br><?php if ($loggedIn) echo // secret information; ?>
PHPSESSID cookie to the illegally obtained one, and they are now viewed by your application as a valid user.PHPSESSID is valid is to use session_regenerate_id(). This very simple command generates a new session identifier, invalidates the old one, maintains session data intact, and has a minimal impact on performance. This command can only be executed after the session has started:session_start(); session_regenerate_id();
session_destroy(), but also to unset $_SESSION data and to expire the session cookie:session_unset();
session_destroy();
setcookie('PHPSESSID', 0, time() - 3600);$remotePrint = md5($_SERVER['REMOTE_ADDR']
. $_SERVER['HTTP_USER_AGENT']
. $_SERVER['HTTP_ACCEPT_LANGUAGE']);
$printsMatch = file_exists(THUMB_PRINT_DIR . $remotePrint);
if ($loggedIn && !$printsMatch) {
$info = 'SESSION INVALID!!!';
error_log('Session Invalid: ' . date('Y-m-d H:i:s'), 0);
// take appropriate action
}To demonstrate how a session is vulnerable, code a simple login script that sets a $_SESSION['isLoggedIn'] flag upon successful login. You could call the file chap_12_session_hijack.php:
session_start();
$loggedUser = $_SESSION['loggedUser'] ?? '';
$loggedIn = $_SESSION['isLoggedIn'] ?? FALSE;
$username = 'test';
$password = 'password';
$info = 'You Can Now See Super Secret Information!!!';
if (isset($_POST['login'])) {
if ($_POST['username'] == $username
&& $_POST['password'] == $password) {
$loggedIn = TRUE;
$_SESSION['isLoggedIn'] = TRUE;
$_SESSION['loggedUser'] = $username;
$loggedUser = $username;
}
} elseif (isset($_POST['logout'])) {
session_destroy();
}You can then add code that displays a simple login form. To test for session vulnerability, follow this procedure using the chap_12_session_hijack.php file we just created:
php -S localhost:8080 command.http://localhost:8080/<filename>.test with a password as password.PHPSESSID cookie.PHPSESSID.For illustration, we are also showing the value of $_COOKIE and $_SESSION, shown in the following screenshot using the Vivaldi browser:

We then copy the value of PHPSESSID, open a Firefox browser, and use a tool called Tamper Data to modify the value of the cookie:

You can see in the next screenshot that we are now an authenticated user without entering the username or password:

You can now implement the changes discussed in the preceding steps. Copy the file created previously to chap_12_session_protected.php. Now go ahead and regenerate the session ID:
<?php
define('THUMB_PRINT_DIR', __DIR__ . '/../data/');
session_start();
session_regenerate_id();Next, initialize variables and determine the logged in status (as before):
$username = 'test'; $password = 'password'; $info = 'You Can Now See Super Secret Information!!!'; $loggedIn = $_SESSION['isLoggedIn'] ?? FALSE; $loggedUser = $_SESSION['user'] ?? 'guest';
You can add a session thumb-print using the remote address, user agent, and language settings:
$remotePrint = md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT'] . $_SERVER['HTTP_ACCEPT_LANGUAGE']); $printsMatch = file_exists(THUMB_PRINT_DIR . $remotePrint);
If the login is successful, we store thumb-print info and login status in the session:
if (isset($_POST['login'])) {
if ($_POST['username'] == $username
&& $_POST['password'] == $password) {
$loggedIn = TRUE;
$_SESSION['user'] = strip_tags($username);
$_SESSION['isLoggedIn'] = TRUE;
file_put_contents(
THUMB_PRINT_DIR . $remotePrint, $remotePrint);
}You can also check for the logout option and implement a proper logout procedure: unset $_SESSION variables, invalidate the session, and expire the cookie. You can also remove the thumb-print file and implement a redirect:
} elseif (isset($_POST['logout'])) {
session_unset();
session_destroy();
setcookie('PHPSESSID', 0, time() - 3600);
if (file_exists(THUMB_PRINT_DIR . $remotePrint))
unlink(THUMB_PRINT_DIR . $remotePrint);
header('Location: ' . $_SERVER['REQUEST_URI'] );
exit;Otherwise, if the operation is not login or logout, you can check to see whether the user is considered logged in, and if the thumb-print doesn't match, the session is considered invalid, and the appropriate action is taken:
} elseif ($loggedIn && !$printsMatch) {
$info = 'SESSION INVALID!!!';
error_log('Session Invalid: ' . date('Y-m-d H:i:s'), 0);
// take appropriate action
}You can now run the same procedure as mentioned previously using the new chap_12_session_protected.php file. The first thing you will notice is that the session is now considered invalid. The output will look something like this:

The reason for this is that the thumb-print does not match as you are now using a different browser. Likewise, if you refresh the page of the first browser, the session identifier is regenerated, making any previously copied identifier obsolete. Finally, the logout button will completely clear session information.
For an excellent overview of website vulnerabilities, please refer to the article present at https://www.owasp.org/index.php/Category:Vulnerability. For information on session hijacking, refer to https://www.owasp.org/index.php/Session_hijacking_attack.