How to prevent PHP sessions being shared between different apache vhosts?

Edit is also the reason why you ALWAYS should set your session_save_path ( http://php.net/manual/en/function.session-save-path.php ) or use database session handling ( http://php.net/manual/en/class.sessionhandler.php ) if you are on an shared webhosting. Somebody can create an session id on there site and chmod it to 777 and use that session id on your site to bypass logins/or get more privileges. It can also be used for SQL injections.

This works because PHP doesn’t enforce what session IDs belongs to what site. I know this because I’ve analysed the C/C++ source code behind sessions in PHP, and because I wondered how this could be possible. So never put too much trust that the $_SESSION array is safe on shared web hosting and you can’t safely use this value in a SQL query.

Some code (file session.c) in PHP from C function php_session_start(); yes, this function is called when you call session_start() from PHP (and the only check I saw was in these lines of code):

/* Check whether the current request was referred to by
 * an external site which invalidates the previously found id. */

if (PS(id) &&
        PS(extern_referer_chk)[0] != '\0' &&
        PG(http_globals)[TRACK_VARS_SERVER] &&
        zend_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]), "HTTP_REFERER", sizeof("HTTP_REFERER"), (void **) &data) == SUCCESS &&
        Z_TYPE_PP(data) == IS_STRING &&
        Z_STRLEN_PP(data) != 0 &&
        strstr(Z_STRVAL_PP(data), PS(extern_referer_chk)) == NULL
) {
    efree(PS(id));
    PS(id) = NULL;
    PS(send_cookie) = 1;
    if (PS(use_trans_sid) && !PS(use_only_cookies)) {
        PS(apply_trans_sid) = 1;
    }
}

The only check is the HTTP Header “HTTP_REFERER”, but we all know it can be faked, so this is “security through obscurity”. The only safe method is to use session_save_path or use a database session handler.

To set session_save_path in the php.ini, you should find more information here http://php.net/manual/en/session.configuration.php.

Or, if PHP is running as an Apache module, you can configure it in the htaccess file of vhost container:

php_value session.save_path "path"

Or even better a PHPINIDir per vhost:

<VirtualHost ip>
[...]
PHPINIDir /var/www/...
[...]
</VirtualHost>

UPDATE [Panique]:

I’m just adding the full solution to this answer, as this might help other people too. A sample full vhost setup:

<VirtualHost *:81>
    DocumentRoot /var/www/xxx1
    <Directory "/var/www/xxx1">
        AllowOverride All
        php_value session.save_path "/var/mysessionforproject_1"
   </Directory>
</VirtualHost>

<VirtualHost *:82>
    DocumentRoot /var/www/xxx2
    <Directory "/var/www/xxx2">
        AllowOverride All
        php_value session.save_path "/var/mysessionforproject_2"
   </Directory>
</VirtualHost>

Leave a Comment