php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #67146 PHP sends session info in the clear when secure is enabled
Submitted: 2014-04-28 15:30 UTC Modified: 2014-04-29 00:40 UTC
From: lightnb at bellsouth dot net Assigned:
Status: Not a bug Package: Session related
PHP Version: 5.5.11 OS: Ubuntu 14.04
Private report: No CVE-ID: None
 [2014-04-28 15:30 UTC] lightnb at bellsouth dot net
Description:
------------
Using session_set_cookie_params() to enable "secure" cookies, PHP will set a cookie with the secure flag, but does not check if the session_start() occurred over a secure connection to begin with.

This creates two problems:

1. The SessionID is translated in the clear to the browser, which defeats the purpose of secure SSL-only Session cookies.

2. Since the cookie is set to secure, it is not submitted when the page is refreshed or another non-SSL page is navigated to. This is correct, but the result is PHP does not get the cookie and PHP re-issues a new session ID cookie, which it then again, submits over plain text. When switching between SSL and non-SSL, this can silently create all sorts of session oddities.

The user can solve this by wrapping the session setup in a block that checks if SSL is enabled, but if the user does not realize this, they may think they are setting up a secure cookie, when in fact they end of with a cookie that is transferred in the clear and reset on each non-SSL page.

Test script:
---------------
// Run over a non SSL connection:
session_set_cookie_params(0,'/','domain.com',true,true);
session_start();

Expected result:
----------------
I think this should throw at least a warning if not a fatal exception.

Either refuse to create the session and create a warning: "Session was not created. You asked for a secure session cookie but this page is running over an unsecured connection".

OR

"Fatal Error: Cannot start secure session over an insecure connection"

Actual result:
--------------
From above:


1. The SessionID is translated in the clear to the browser, which defeats the purpose of secure SSL-only Session cookies.

2. Since the cookie is set to secure, it is not submitted when the page is refreshed or another non-SSL page is navigated to. This is correct, but the result is PHP does not get the cookie and PHP re-issues a new session ID cookie, which it then again, submits over plain text. When switching between SSL and non-SSL, this can silently create all sorts of session oddities.

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-04-28 23:55 UTC] stas@php.net
PHp can not know if the connection is secure or not, since PHP has no idea what network infrastructure between the end client and PHP looks like. There could be relays, VPNs, multiple routers and load balancers adding and removing layers of SSL... And PHP code be a responder at the end of FastCGI protocol which doesn't have any knowledge even of the nearest hop, let alone all the hops on the road. So checking for SSL on the last hop is useless security-wise, and may break many valid setups which add SSL layer later. 

The secure setting is not for PHP, it is for the browser - that does know if it's using HTTPS or not to connect. PHP, however, has no good way to know if the browser used HTTPS or not and if it will be using HTTPS in the future, since PHP may not be talking to the browser directly.
 [2014-04-28 23:55 UTC] stas@php.net
-Type: Security +Type: Feature/Change Request
 [2014-04-29 00:11 UTC] stas@php.net
-Status: Open +Status: Not a bug
 [2014-04-29 00:11 UTC] stas@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php


 [2014-04-29 00:40 UTC] rasmus@php.net
Yes, just to reiterate what Stas said here, an extremely common architecture is to terminal SSL at the load balancer and run non-SSL behind it. Most of these setups have ways to set a special header informing the backend web servers that the client connection is encrypted, but unfortunately there is no standard way to do this. You have to do this check yourself at the application level to match how your SSL-terminating device is passing this on. If we hardcoded some check in PHP we would be flooded with bug reports about us breaking perfectly secure setups.

You can read a good description here:

http://www.lullabot.com/blog/article/setting-ssl-offloading-termination-f5-big-ip-load-balancer

I work at Etsy and our architecture is similar. I would guess most larger sites are doing something along these lines.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Mon May 06 07:01:32 2024 UTC