Skip to Content
Course content

173: Secure Session Configuration

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I once worked with a junior dev who was baffled why their "secure" admin panel was being hijacked, even though they had a strong password and a working login system. They had the basic session logic down, but they were using the default PHP settings. I asked them to open the browser console and type document.cookie. They were shocked to see the PHPSESSID staring back at them in plain text.

// The "Standard" way most people start sessions
session_start();

$_SESSION['user_id'] = 42;
$_SESSION['role'] = 'admin';
echo "You are logged in!";

The problem isn't the code above—it's what's missing. By default, PHP creates a session cookie that is accessible to any JavaScript running on the page. If your site has a single XSS (Cross-Site Scripting) vulnerability—maybe a search bar that doesn't sanitize input—an attacker can inject a script to send that session ID to their own server. Once they have that ID, they don't need the password; they just pretend to be that user.

Closing the JavaScript Backdoor with HttpOnly

The first thing we need to do is tell the browser: "Do not let JavaScript touch this cookie." We do this with the HttpOnly flag. When this is set, document.cookie will simply ignore the session ID, making it significantly harder for an attacker to steal the session via XSS.

You can set this in php.ini, but in a real-world project, you often don't have access to the server config. Instead, pass an options array directly into session_start():

session_start([
    'cookie_httponly' => true,
]);

Stopping Man-in-the-Middle Attacks with Secure and SameSite

If your site is running on HTTPS (which it should be), you have another lever to pull: the Secure flag. Without it, if a user accidentally hits an HTTP version of your site, the browser will send the session cookie in plain text over the wire. A packet sniffer on a public Wi-Fi network can grab that ID in seconds.

While we're at it, we should address SameSite. This attribute tells the browser whether to send the cookie with cross-site requests. Setting this to Lax or Strict is your first line of defense against Cross-Site Request Forgery (CSRF) attacks, preventing other websites from triggering actions on your site using the user's active session.

Here is how I configure sessions for any production app I build. I prefer passing these options as an array to keep the configuration explicit and contained:

session_start([
    'cookie_lifetime' => 0,             // Cookie expires when browser closes
    'cookie_path' => '/',              // Available across the whole domain
    'cookie_domain' => 'yourdomain.com', 
    'cookie_secure' => true,           // Only send over HTTPS
    'cookie_httponly' => true,         // Block JavaScript access
    'cookie_samesite' => 'Lax',        // Prevent CSRF
    'use_strict_mode' => true,         // Prevent session fixation
]);

I mentioned use_strict_mode. This is a subtle but critical setting. Without it, PHP will accept a session ID provided by the browser even if PHP didn't create it. An attacker could provide a specific ID to a victim, wait for them to log in, and then use that same ID to enter the account. Strict mode tells PHP: "If I didn't generate this ID, I'm not using it."




📋 Practical Task

Hardening a Vulnerable User Dashboard

You have been handed a legacy dashboard.php file that is currently using default, insecure session settings. Your task is to rewrite the session initialization to meet modern security standards.

Requirements:

  • Modify the session_start() call to ensure the session cookie cannot be accessed by document.cookie.
  • Ensure the cookie is only transmitted over encrypted (HTTPS) connections.
  • Implement Lax SameSite protection to mitigate CSRF risks.
  • Enable strict mode to prevent session fixation attacks.
<?php
// CURRENT INSECURE CODE:
session_start();

if (!isset($_SESSION['user_id'])) {
    die("Access Denied");
}

echo "Welcome to your secure dashboard!";
?>
Rating
0 0

There are no comments for now.

to be the first to leave a comment.