37

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?

Jenz
  • 8,280
  • 7
  • 44
  • 77
Jeff
  • 947
  • 2
  • 9
  • 23
  • where are you sending your session cookie, or which mechanism sets it, in your application? that's where you should implement this. – eis Mar 06 '14 at 10:40
  • if you're talking about default PHPSESSID cookie, this question sounds like a duplicate of [this](http://stackoverflow.com/questions/6821883/set-httponly-and-secure-on-phpsessid-cookie-in-php) – eis Mar 06 '14 at 10:42
  • its gets set in the code and is used for logging in and retrieving user data. Can it be set in the htaccess file? – Jeff Mar 06 '14 at 10:42
  • depends. is it the default PHPSESSID cookie used by PHP session system, or a custom one? – eis Mar 06 '14 at 10:42
  • it is the default one – Jeff Mar 06 '14 at 10:43

4 Answers4

57

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);
Perry
  • 11,172
  • 2
  • 27
  • 37
45

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...).

eis
  • 51,991
  • 13
  • 150
  • 199
  • 1
    re the "nasty surprise" thing, of course it's always worth warning people :) but preventing session cookies from being sent over http is sort of the point of the exercise here. – John May 06 '16 at 11:37
  • I was checking in non-https page... how silly me 0_0. Thx @els – sk8terboi87 ツ Aug 22 '19 at 02:54
15

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.

danielson317
  • 3,121
  • 3
  • 28
  • 43
0

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;
}

}
Aranxo
  • 677
  • 4
  • 15