How to secure PHP sessions against CSRF attacks
Configure PHP session cookies with SameSite and HttpOnly flags to prevent Cross-Site Request Forgery attacks.
Configure your PHP session handler to enforce SameSite cookie attributes and HttpOnly flags to mitigate Cross-Site Request Forgery risks. These steps apply to PHP 8.3.x running on Linux distributions like Ubuntu 24.04 or AlmaLinux 9.
Prerequisites
- Operating system: Ubuntu 24.04, AlmaLinux 9, or Debian 12
- PHP version: 8.3.x installed via package manager or source
- Web server access: Apache or Nginx with PHP-FPM
- Root or sudo privileges to modify
php.inifiles - Basic understanding of PHP session handling and cookie attributes
Step 1: Locate the active PHP configuration file
Identify the specific php.ini file used by your web server to ensure changes apply to the correct environment. Run the following command to check the active configuration path:
php -i | grep "Configuration File"
You will see output similar to this:
Configuration File (php.ini) Path => /etc/php/8.3/cli/conf.d
For Apache or Nginx setups, the file is usually in /etc/php/8.3/apache2/php.ini or /etc/php/8.3/fpm/php.ini. If using a shared hosting environment, locate the file via your control panel's PHP settings.
Step 2: Enable HttpOnly for session cookies
Prevent JavaScript access to session cookies to stop XSS attacks from stealing session tokens. Open the configuration file using a text editor and add or modify the session.cookie_httponly directive:
sudo nano /etc/php/8.3/apache2/php.ini
Add the following line inside the file:
session.cookie_httponly = 1
Save the file and exit the editor. This setting ensures browsers send cookies only over HTTPS and blocks client-side scripts from reading them.
Step 3: Set SameSite to Strict or Lax
Block cross-site requests from sending cookies by setting the session.cookie_samesite directive. Open the same configuration file and add this line:
session.cookie_samesite = Strict
Using Strict prevents the browser from sending the cookie with third-party requests, which is the most secure option for CSRF protection. If you need to allow some cross-site navigation, use Lax, but Strict is recommended for sensitive applications.
Step 4: Regenerate session IDs on login
Force a new session ID when a user logs in to prevent session fixation attacks. Add the following line to the same php.ini file:
session.use_strict_mode = 1
This setting ensures that a new session ID is generated whenever a session is created, making it harder for attackers to predict or hijack existing sessions.
Step 5: Disable session regeneration on every request
Improve performance by disabling automatic session regeneration on every request unless necessary. Add this line to the configuration file:
session.gc_maxlifetime = 1440
This sets the session timeout to 24 minutes (1440 seconds). Adjust this value based on your application's needs. You can also add session.cookie_lifetime = 0 to make cookies expire when the browser closes, though this may impact user experience.
Step 6: Restart the web server
Apply the changes by restarting the web server to reload the PHP configuration. For Apache, run:
sudo systemctl restart apache2
For Nginx with PHP-FPM, run:
sudo systemctl restart php8.3-fpm
Verify that the service restarted without errors by checking the status output.
Verify the installation
Test that the session cookies are configured correctly by creating a simple PHP script. Create a file named test_session.php in your web root:
echo '';
phpinfo();
echo '
';
Access the script via your browser and search for "Session" in the output. Look for these lines:
cookie_httponly: 1
cookie_samesite: Strict
use_strict_mode: 1
If these values appear, the configuration is correct. Open the browser's developer tools, go to the Application tab, and inspect the cookies. Confirm that the HttpOnly and SameSite flags are set for the session cookie.
Troubleshooting
Common issues you may encounter when securing PHP sessions include:
- Error: "session.cookie_samesite is not a supported value"
This occurs when using an older PHP version that does not support the SameSite attribute. Upgrade to PHP 8.1 or later, or manually set the cookie attribute in your code usingsession_set_cookie_params(). - Error: "Cannot change session cookie attributes after session has started"
You cannot modify session cookie settings aftersession_start()is called. Move allsession_set_cookie_params()calls beforesession_start()in your application code. - Error: "Session cookie not sent due to missing SameSite header"
Some browsers block cookies if the SameSite header is missing. Ensure your PHP version supports the directive and that the web server is not overriding it with custom headers. - Error: "Session fixation vulnerability persists"
If session fixation is still possible, ensuresession.use_strict_modeis enabled and that you regenerate session IDs on every login attempt usingsession_regenerate_id(true). - Error: "Performance degradation due to frequent session regeneration"
Regenerating sessions on every request can slow down your application. Only regenerate sessions on sensitive actions like login or password changes, not on every page load.
If issues persist, review your php.ini syntax for typos or missing semicolons. Check Apache or Nginx error logs for any warnings related to session handling. Ensure that no other modules or extensions are overriding the session configuration. Test the setup in a controlled environment before deploying to production.