views:

4860

answers:

6

When sending the user to a checkout page, they are switched from http://mysite.com to https://mysite.com. As a result, $_SESSION variables are lost.

The site has a valid SSL certificate which may or may not be of some use.

A: 

This may not be possible since the cookie seems to be getting lost. The browser you're using must think it's for a completely different domain.

What browser are you using specifically?

Allain Lalonde
+1  A: 

By default I would expect a browser to treat connections to http and https as completely different sessions. Although the convention is that http://someUrl/ and https://someUrl/ will point to the same page it isn't guaranteed. You could have completely different sites running on port 80 (http) and port 443 (https).

I don't know PHP, but generally I would not expect session variables to be freely available between secure and non-secure sessions e.g. I wouldn't expect the credit card number from my last checkout to be available to all the subsequent insecure pages I visit.

Forgive the non-authoritative answer but I thought I'd chuck in my 2c since there aren't many answers.

it depends
+10  A: 

When you switch between the HTTP and HTTPS services on the same server, your HTTP session ID is not being passed to the HTTPS session. You can set it by passing the session ID from the HTTP page to the HTTPS page in one of three possible ways:

"session_start() creates a session or resumes the current one based on the current session id that's being passed via a request, such as GET, POST, or a cookie" from PHP: session_start

When you are using sessions, you will normally start your script with "session_start()". If the browser has a session ID cookie set, session_start() will use that session ID. If the browser does not have a session ID cookie set, session_start() will create a new one.

If the session ID is not set(in your example, the browser is creating a new session ID cookie for the HTTPS session), you can set it using the session_id() function. session_id() also conveniently returns the session ID as a string. So

...

$currentSessionID = session_id();

...

sets the $currentSessionID variable equal to the current session ID, and

...

session_id($aSessionID);

...

sets the sessionID cookie in the browser to $aSessionID. from PHP: session_id

Here's an example with two scripts. One is accessed via HTTP and the other is accessed via HTTPS. They must be on the same server to maintain session data.

Script 1(HTTP):

<?php

// This script will create a session and display a link to your secure server address
// to transfer your session ID. In this example, the secure page to receive the session
// ID is located at http://www.yoursite.com/safePages/securePage.php

// Start a session using the current session ID stored in a cookie, or create
// a new session if none is set.
session_start();

$currentSessionID = session_id();

// Set a variable that will be retrieved with the HTTPS script.
$_SESSION['testvariable'] = 'It worked';

// $secureServerDomain is the domain of your secure server
$secureServerDomain = 'www.yoursite.com';

// $securePagePath is the path to the page that will receive and set the session ID.
$securePagePath = '/safePages/securePage.php'

echo '<a href="https://' . $secureServerDomain . $securePagePath . '?session="' . $currentSessionID . '">Click here to transfer your session to the secure server</a>';

?>

Script 2(HTTPS):

<?php

// Retrieve the session ID as passed via the GET method.
$currentSessionID = $_GET['session'];

// Set a cookie for the session ID.
session_id($currentSessionID);

// Start a session.
session_start();

// Test retrieval of variable set when using HTTP.
if (!empty($_SESSION['testvariable'])) {
      echo $_SESSION['testvariable'];
} else {
      echo 'It did not work.';
}

?>

For this to work the HTTP and HTTPS servers must run on the same physical machine. There are some security flaws here, so I would not use this code to transfer sensitive information. It is just meant as a workable example.

When I ran into this problem before, I came up with the above as a quick fix, but I just remembered the original cause of the problem. I was going from http://www.mysite.com/page.php to https://mysite.com/page.php (notice the lack of "www"). Make sure that http://www.mysite.com/page.php will link to https://www.mysite.com/page.php and http://mysite.com will link to https://mysite.com/page.php.

PS, I didn't actually run these scripts so there may be a typo or two that prevents them from running properly as is.

Jacob
Using additionally a salted hash would secure this procedure.
Gumbo
I can't see the nature of the security issues here - know any resources that describe them?
waitinforatrain
+3  A: 

Sounds like the session cookie is set to be secure. Cookies have a "secure" flag which, if set to true, means that the cookie won't be sent to non-https sites. PHP is probably using that for its session cookies. You can change this with the session_set_cookie_params function, or with the session.cookie_secure setting in php.ini.

JW
A: 

Looks like your session cookie is created with the secure flag, but there's something with the url of your checkout page due to which the session cookie isnt being passed over.

Or probably, your session cookie isnt secure - just that the url of the checkout page is different enough (http://mysite.com vs http://www.mysite.com) that the browser isnt sending the cookie.

If you'd like to read more on flipping over from http to https and vice versa - do take a look at at my writeup on selective ssl :-)

A: 

We had this issue as well. It turned out to be because we were using the suhosin patch on our PHP installation. We fix it by setting suhosin.session.cryptdocroot = Off in /etc/php.d/suhosin.ini.

For the suhosin manual about suhosin.session.cryptdocroot see http://www.hardened-php.net/suhosin/configuration.html#suhosin.session.cryptdocroot.

We originally found the fix from this blog post: http://www.yireo.com/blog/general-news/315-switch-between-http-and-https-looses-php-session.

Tom