Jeff
Jeff

Reputation: 1017

Session cookies http & secure flag - how do you set these?

Just received the results of a security audit - everything clear apart from two things

Session cookie without http flag.

Session cookie without secure flag set.

The application is coded in php and the suggestions to fix are:

  1. set session cookie with http only flag
  2. set session cookie with secure flag

I have looked at examples but don't fully understand how to implement on a Linux server. I don't have access to the .ini file . Is it possible to set these in the htaccess file?

Alternatively, how and where do I implement in the code?

Upvotes: 44

Views: 89174

Answers (5)

theking2
theking2

Reputation: 2813

I typically use this to set the session cookie:

<?php
define('DEBUG', true); // or false in production

session_start([
    'name' => DEBUG ? 'SessionId' : '__Secure-SessionId',
    'cookie_lifetime' => 0,
    'cookie_path' => '/',
    'cookie_secure' => !DEBUG, // Set to true only if HTTPS is available in production
    'cookie_httponly' => true,
    'cookie_samesite' => 'Strict',
    'sid_length' => 96,
    'sid_bits_per_character' => 5,
    'use_strict_mode' => true,
    'referer_check' => $_SERVER['HTTP_HOST'],
]);

which will create a session with increased entropy in the session cookie name, requires a secure session, make sure roque refers have no chance at my logon page among other things.

According to MDN prefix "__Secure-" must be set for secure sessions.

Upvotes: 0

Aranxo
Aranxo

Reputation: 1183

You can set these parameters also with session_set_cookie_params before you start the session with session_start.

Here is the a part/the start of my php session class which sets some parameters automatically to the right value and others to some defaults. You can change these by overriding them with the parameter $moreoptions.

class Session {

/**
* The flag to define if we work under SSL
* @var bool
* @access private
*/
private static bool $IS_SSL;

/**
* The session cookie parameters
* @var array<string,mixed>
* @access private
*/
private static array $cookieparams = array('lifetime' => 86400,
                                           'path' => '/',
                                           'httponly' => true,
                                           'samesite' => 'Strict');

/**
* Starts the session with session_start()
*
* Note: If the session already has started nothing will happen
* @param array<string,mixed> $moreoptions   Optional: Array with cookie params to overrule the defaults
* @param string $sessionname                Optional: Another name for the session
* @return void
* @access public
*/
public static function start(array $moreoptions = array(), string $sessionname = '') : void {
    if (!self::hasStarted()) {
        self::$IS_SSL = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on';

        if (!empty($sessionname)) {
            session_name($sessionname);
        } elseif (self::$IS_SSL) {
            session_name('__Secure-PHPSESSID');
        }

        self::$cookieparams['domain'] = $_SERVER['SERVER_NAME'];
        self::$cookieparams['secure'] = self::$IS_SSL;

        session_set_cookie_params(array_merge(self::$cookieparams, $moreoptions)); 
        session_start();
    }
}

/**
* Tests if a session was started
* @return bool True if a session is running
* @access public
*/
public static function hasStarted() : bool {
    return session_status() === PHP_SESSION_ACTIVE;
}

}

Upvotes: 0

danielson317
danielson317

Reputation: 3288

I know this specifically said they do not have access to the .ini file but for those who get here via search results the .ini settings look like:

session.cookie_httponly = 1
session.cookie_secure = 1

The cookie_secure is already present by default in most ini files but commented out. So uncomment that line and set the 1. The httponly line is also already present but not commented out but defaults to 0. So you must hunt it down and set it.

Upvotes: 15

eis
eis

Reputation: 53462

Since you asked for .htaccess, and this setting is PHP_INI_ALL, just put this in your .htaccess:

php_value session.cookie_httponly 1
php_value session.cookie_secure 1

Note that session cookies will only be sent with https requests after that. This might come as a surprise if you lose a session in non-secured http page (but like pointed out in the comments, is really the point of the configuration in the first place...).

Upvotes: 48

Perry
Perry

Reputation: 11700

You can set them before you send the header. Just add these line below in you code.

<?php
// **PREVENTING SESSION HIJACKING**
// Prevents javascript XSS attacks aimed to steal the session ID
ini_set('session.cookie_httponly', 1);

// **PREVENTING SESSION FIXATION**
// Session ID cannot be passed through URLs
ini_set('session.use_only_cookies', 1);

// Uses a secure connection (HTTPS) if possible
ini_set('session.cookie_secure', 1);

Upvotes: 64

Related Questions