Hi,

I was speaking to a webhost yesterday, over the phone, and I happened to mention a PHP problem I've been having lately.

The problem is that I've been having trouble passing session data from non secure webpages over to SSL. Apparently, session data is lost when you cross over to a different domain.

Anyway, this guy insisted that there is a way to declare what domains your session variables will be passed on to. I think it's something to do with a built in function that relates to sessions, but I'm not sure.

In any case... the guy was REALLY keeping his cards close to his chest and wouldn't elaborate any further (I think he wanted me to phone his mega expensive support telephone number!).

I was just wondering if anyone here knew about any functions or other "tricks" that would give us the opportunity to declare what domains we would like our session data to be passed to.

I've looked at the online PHP manual and to be honest, I found it a little bit confusing.

Thanks.

    [man]session_save_path[/man] is probably what was being hinted at.

    But that won't help you if you use cookies for storing the session ID. The cookies themselves will only be served back to the domain that set them. Otherwise, it would be possible to steal cookies.

    So you'll need to use another mechanism for passing the session ID, like a form variable. I think you can use [man]session_id[/man] once you have it from the client.

      Maybe I've read it wrong... but my understanding of if (based on nothing more than what I've read from the manual) is that session_save_path is a function that is used for simply obtaining the path where your session cookies are stored (so, most of the time, it'll probably return "/temp" or something like that). But let me stress, that I COULD be wrong there.

      I appreciate your helpful reply, but I'm still searching for that magical function that's going to solve this pesky problem once and for all.

      I thought that maybe it had something to do with session.cookie_domain or session.cookie_secure (taken from the manual), but AGAIN I must confess that I haven't really got a clue about how to handle this kind of stuff.

        Actually... I've had another look at the manual and I think session_set_cookie_params could be the thing that I've been looking for.

        The trouble is... (as ye shall see!), the manual does a really crap job of explaining how to use the function.

        This particular problem (how to pass session data over multiple domains) has plagued the forum for years and so far nobody has came up with a rock solid solution. It would be really good if we could nail this problem once and for all.

          The problem is not exactly one of passing the session data over multiple domains. The session data is in the directory specified by session_save_path, which as you mention is usually /tmp or some such thing that is easily accessed across multiple domains (as long as they are on the same server, of course).

          The problem is identifying the users, so PHP knows which session file to load.

          Usually cookies are used to identify the client. But cookies are not cross-domain (for security reasons), which is where the problem lies. So you need to identify the user using a mechanism other than cookies. Then you can load the right session data.

          Suppose you have www.example.com and www.example.net, and want to pass users from the .com site to the .net and maintain their session.

          On www.example.com, have a link to the other server:

          <?php
          session_save_path("/tmp");
          session_start();
          ?>
          <!-- bunch of html here -->
          <?php echo '<a href="http://www.example.net/somepage.php?sessionid='.session_id().'">Go to example.net!</a>'; ?>
          

          Then on www.example.net, somepage.php:

          <?php
          if (!empty($_GET['sessionid'])) {
              session_id($_GET['sessionid']);
          }
          session_save_path("/tmp");
          session_start();
          

          I haven't tested it, but in theory that should work.

            Hmm... If I'm not mistaken, the example I just posted is vulnerable to session fixation:

            1- Bad guy's site gives you a link somepage.php?sessionid=00000
            2- You click on it, do stuff during that session
            3- Bad guy accesses site using session id of "00000", hijacking your login

            I can't think of a way around that. Checking referrer would help, but is not entirely reliable.

            I guess you could set a session variable on the other server before forwarding the user, then if it is not set when the other page receives the user then you know the session doesn't exist and can declare shenanigans. But then the bad guy just has to set up a real session and give you that ID. Hmm...

              Thanks for that.

              I think the best way round this problem, that I know of, is the technique of saving all the session data to a mysql database when the user clicks "Go to checkout" (or whatever).

              When the users goes to the new site, you would have the session ID joined onto the URL. Finally, when the person arrives at the next domain, a MySQL query is automatically executed that calls up everything that's associated with the session ID (on the URL).

              So far, that's the best solution I've heard of.

              But, it has at least two flaws (and I hope somebody will be able to help me with this):

              • Over time your database would get clogged up with lots of redundant information. So, there would need to be some sort of garbage removal system in place.

              • I'm not sure about this, but is it in the realms of possibility that two users could somehow end up with the same session ID? If that ever did happen, and I think it probably could, then I think it would surely cause chaos with the application.

              Any advice on the above issues would be MEGA appreciated.

              Thanks!

              web development company

                I might be way off here, but here are my thoughts.

                My thought about this involves 3 steps:

                1.) On the page before the redirect to the https secure page, you could write the session cookie value to a hidden input (ie, using the session_id() function - which can be used to get or set the session id -- see the manual)

                2.) The https page would retrieve that value of the hidden input session id. The https page makes a call (via fsockopen) to a script on the non-secure domain passing in the session id value and the $_SESSION variable name you need to get the value for.

                3.) The PHP script on the non-secure domain that gets called does the folowing:
                a.) sets the session ID based on the value passed to it
                this is done using the session_id() function which must be called BEFORE session_start() -- see the manual
                b.) looks up the value for the variable passed in, and returns that value - I believe simply using echo (note this won't be a html page so you might need to set some headers, but I don't think so).

                -- One thing I'm not positive about is whether it's OK to open a socket connection to a non-secure domain within a secure https page (but I think it is).

                • not a simple solution to implement, but it will be a solution if you work at it.

                • HTH

                  Still no solution to the session fixation problem...

                  freebie,
                  fsockopen is unnecessary because the two sites are probably on the same server. It doesn't solve the problem because you still need some kind of cross-site ID for the browser to identify itself, and cross-site IDs may be used in session fixation.

                  Davidc316,
                  The problem is not that users might accidentally get the same session ID, but that someone else with their own web site might trick users into going to your site with a specific session ID. If you know somebody's session ID, you can access the web site using that session ID and hijack their login. Seesion IDs are not guessable, but if you can cause a user to use a specific session ID on another site then you don't need to guess. That's how session fixation attacks work.

                  Cookies are safe for passing session IDs because they are not cross-domain. But you need something cross domain here, like form variables. But being cross-domain also opens up the session fixation problem.

                  As far as I can tell, referrer checking is as good as it gets here. Make sure the user isn't being sent in from another site, and other sites can't trick users into going to your site with a session ID of their choosing. But if the user has referrers disabled there is no way to tell where they are coming from.

                  The only real solution is to avoid the cross-domain situation completely. Put your secure and non-secure sites on the same domain.

                    have you read this already.. seems ive been to this site before...

                    http://www.phpbuilder.com/columns/chriskings20001128.php3

                    this may be more complicated:

                    have each server run a progream that accepts requests for sessions... if the ipaddress of the request is from the other server.. it will return with the session that it has...

                    so each php script must :
                    1) check for the session is
                    2) if it is not local, ask the other server if it exists over there
                    3) get the session from the other server, and have it removed so there is only 1 version of the session between the computers
                    4) store and use it as a local session

                    don't know if you would like to put this much work into this however

                      That's still vulnerable to session fixation. The problem is not in passing the session data from one server to another (if both sites are on the same server, it's already there) but of passing the user from one domain to another and still being able to identify them.

                      The article you linked to was written before session fixation attacks were widely known, and the method it describes (which is basicly equivalent to what I first posted) is not secure.

                        Okay, I've done a bit more research...

                        Davidc316, if the two domains are actually just different hosts on the same domain (like www.example.com and secure.example.com) then the following may allow the cookie to be used across both hostnames:

                        ini_set("session.cookie_domain",".example.com");

                        Put that before session_start(). Note that the first dot in ".example.com" is important, as most browsers expect at least two dots in the domain property of the cookie.

                        As for session fixation...

                        PHP in it's default configuration accepts session IDs in URLs, like so:
                        http://www.example.com/mypage.php?PHPSESSID=00000
                        By default it accepts the ID without checking that the session actually exists, and without checking the referrer. All websites using PHP in its default configuration are highly vulnerable to session fixation attacks.

                        To make sessions reasonably secure, you need to set the session.use_only_cookies configuration option.

                          Thanks, for that.

                          I've played around with your function, but unfortunately I can't get it to work. The session variables are still not being passed from site X to site Y.

                          You've given me a good run for my money and thanks for all the help. However, I must confess that I'm now resigned to the fact that I'm never going to solve this problem in the way I would have wanted to. It looks like there's not much left to do except to resort to using MySQL tables to store the variables.

                          Thanks again.

                            just some thoughts

                            In response to your comment below
                            "fsockopen is unnecessary because the two sites are probably on the same server. It doesn't solve the problem because you still need some kind of cross-site ID for the browser to identify itself, and cross-site IDs may be used in session fixation. "

                            • I think in this case fsockopen (or a webservice call) would be needed even though it's on the same server because your need to get the results of another script from within a script.
                            • As for being vulnerable to session fixation, I don't think this would be the case. Cookies are being used and the only place it writes out the session id is in a hidden input field (for the hacker to try to get around this, he/she would need to POST values to your server, in which case you can simply verify the referer - or is that spoofable?)

                              Surely the best way would be to keep the data on the server. That way, you don't need to pass the session around to get the data - just the ID.

                                Write a Reply...