54

Lots of sites appear to support https but don't use secure cookies. I want to make my site use secure cookies but to allow for some content to be accessed using http instead.

A sensible way to do this appears to be to have a secure cookie for the real session, and a non-secure cookie which is just a flag to say if the user is logged in or not (to display different things in the header, like a logout link instead of a login link). This cookie wouldn't contain any "real" session information and is just so that the site can show pages slightly differently for logged-in users compared to logged-out ones on http portions of the site.

Having the whole site as https is another option but this appears to be quite a bit slower than plain http and so is not really ideal.

Why don't sites use this kind of set-up and have secure cookies? The possibility of cookie theft seems to make secure cookies a necessity nowadays. Is there a better way to achieve the same thing?

David Gardner
  • 6,952
  • 4
  • 35
  • 37
  • 4
    Maybe because secure cookies and HTTP don't play well together? I tried to implement exactly this, but the secure cookies seem to get wiped out when the user leaves HTTPS (so far as I can tell). http://stackoverflow.com/questions/16734090/http-pages-are-removing-my-secure-cookies – Ned Twigg May 24 '13 at 11:40

4 Answers4

31

The solution you propose seems like it would work, as long as you don't mind non-authorized people being able to view the non-secure (http) part of the site 'as if they are logged in' - ie as long as the http part of the site does not contain any sensitive information, and the only difference between logged in and not-logged-in users is something harmless in the header.

The reason it is not used very often may be one of:

  • This scenario may just not be very common. Usually if you care enough to make part of your site secure, you'd restrict the login session just to that secure part, or you'd make the entire site always use HTTPS (like Paypal).
  • Pre-existing solutions exist which are secure and which are capable of more than this, for example logging in someone at an HTTPS login form and maintaining that session while transferring them back to HTTP. OpenID's an example. Also think flickr or gmail: their sign in page is always HTTPS, but once the session's started you migrate back to HTTP while maintaining the session securely.

Update (Aug 2014)

Since I wrote this back in 2009, the practice of having a secure connection for the login screen but dropping back to HTTP once logged in has all but disappeared.

The overhead of using HTTPS side-wide is not seen as much of a big deal anymore. The new SPDY protocol pioneered by Google (now evolved into HTTP/2) is supported cross-browser and by major web servers and improves HTTPS speed.

And lastly, privacy is seen as more important than ever, even for actions that aren't critical to the authentication, such as writing comments, uploading photos, and more.

Google has even said recently that sites which are HTTPS-only will start to benefit in search engine rankings.

thomasrutter
  • 114,488
  • 30
  • 148
  • 167
  • 4
    Do you have a link to something which explains how OpenID (or other sites) manage to migrate you back to HTTP but maintain session security? This is what I am failing to understand : having https for login and then insecure cookies and http sessions on a lot of sites... – David Gardner Apr 07 '09 at 13:07
  • 2
    The things that most need protecting are the login credentials: whatever you supplied to log in (username/password, or certificate). With OpenID these are sent between yourself and the OpenID provider over HTTPS. OpenID communicates with the client site directly, not needing to send anything – thomasrutter Apr 07 '09 at 13:29
  • sensitive back to the client, but sending a different set of credentials to the client site - ie proof of your OpenID URL encoded with the OpenID provider's private key, so the client site knows that the OpenID provider vouches for this person. Then, the client site maintains the session based – thomasrutter Apr 07 '09 at 13:31
  • ... on a session ID, which is single use and does not reveal the user's credentials or personal identity from that session ID. The risk of having the session hijacked (XSS, etc) still exists, but it is secure in that even if that happens, the attacker can't get your login details or OpenID account, – thomasrutter Apr 07 '09 at 13:34
  • 1
    OpenID is too complicated to provide security, in my opinion, because ordinary people cannot understand how the security works. Other sites that log you in on an HTTPS host and then transfer you to a HTTP host, the general idea is that at least the login credentials were not sent in plain text. – thomasrutter Apr 07 '09 at 13:37
  • 1
    Session hijacking after the login has been performed was something that I was thinking about, and it seems that the only way to avoid this is to use secure cookies. Thanks! – David Gardner Apr 07 '09 at 15:11
  • Secure cookies and HTTPS won't do much to help with that. For example, they don't help with attacks such as XSS or CSRF. It will prevent an attacker reading the contents of the cookie IF you have no XSS vulnerabilities, but clickjacking and CSRF don't even need to attacker to read the cookie. – thomasrutter Apr 08 '09 at 03:35
  • 18
    So a web application, like stackoverflow, has tsl/ssl on login and everything else http. The password can't be stolen, but others can get the session by taking the cookie. How could this be secure? It's even better than a password, the session is what we're trying to protect – Horatiu Jeflea Dec 07 '10 at 11:23
  • 4
    It's a question of how much you're prepared to compromise and how important what you're dealing with is. If you're allowing people to discuss cat photos you may decide that HTTPS is not warranted. Sites that maintain a session without HTTPS are able to take steps to prevent session highjackers being able to perform certain high-impact actions such as changing their (or someone else's) password or email address without re-confirming their password (over HTTPS, ideally). – thomasrutter Sep 09 '11 at 07:25
  • @thomasrutter, SPDY is dead and no longer relevant. – Pacerier Jul 24 '15 at 02:21
  • SPDY will live on as HTTP/2. For now though, it's not dead yet. I'm using it right now to access Stack Overflow. Maybe re-post that comment mid-2016 – thomasrutter Jul 24 '15 at 03:43
11

From a security standpoint, you should never trust any content sent over a non-secured connection. So with that in mind, then it is safe to use a cookie sent over an unencrypted connection only if the cost of theft or misuse of that cookie is approximately zero.

With that in mind, most sites are designed such that the data isn't allowed to "leak" between the channels. After all, data coming from the encrypted side is usually privileged, and therefore shouldn't be allowed in the normal channel, while data coming from the unencrypted channel is potentially spoofed, and shouldn't be trusted.

If you have data that doesn't fit those generalizations, then feel free to do with it as you please.

tylerl
  • 30,197
  • 13
  • 80
  • 113
9

Transferring session cookies over HTTP has been bothering me for a while. I think the technique you described is the only sane way to secure cookies while making it possible for logged in users to browse HTTP pages as if being logged in. However, I've rarely seen this implemented.

Why don't sites use this kind of set-up and have secure cookies?

I think the main reason for lack of adoption is risk management:

  • Stealing session tokens via eavesdropping is much harder than e.g. cross-site scripting (assuming there is a vulnerability). You need access to the network (e.g. user's LAN or ISP). Thus, according to risk-based prioritization developers should tackle XSS issues first because it provides a much bigger attack surface (the probability of an attack is much higher).
  • The same is true for CSRF and UI redressing (aka click-jacking).
  • If the business impact of sessions being hacked is high (e.g. storing credit cards for later use in a web shop), you might be better off restricting your whole site to HTTPS.

Another reason can be usability concerns: With your proposed scheme you're effectively managing two concurrent sessions for a single user. This is easy enough as long as the logged-in-flag is the only state stored in the insecure session. If you can also change settings like language and country from within both sessions it can get messy (to implement or use).

Is there a better way to achieve the same thing?

From The Web Application Hacker's Handbook:

If HTTP cookies are being used to transmit tokens, these should be flagged as secure to prevent the user's browser from ever transmitting them over HTTP. If feasible, HTTPS should be used for every page of the application, including static content such as help pages, images, and so on.

Seriously, make the whole site use HTTPS. A few years back this might not have been feasible mainly because of CDNs not providing HTTPS support. However, today it's mainly a question of balancing development and operational costs.

Pankrat
  • 5,206
  • 4
  • 31
  • 37
  • I agree that HTTPS for the whole site is the best solution, but if you upturn David's idea a bit, you get a good solution, even when using HTTPS for all pages. In this [example](http://stackoverflow.com/questions/5843305/switching-between-http-and-https-pages-with-secure-session-cookie), the session cookie is left unprotected, but another safe cookie makes sure of the authentication. This way you can separate the two concerns of maintaining the session and authentication. – martinstoeckli Nov 02 '11 at 12:52
  • Yes, that's definitely a good solution if implemented properly. All I'm saying is that if you care enough to secure your session cookies against eavesdropping you might as well go all the way to whole site SSL and not risk forgetting to check whether the customer is currently using his secure or insecure session to view or update any restricted data. – Pankrat Nov 12 '11 at 01:35
1

I'm fully aware that the recommended practice is to just force SSL on the entire site. However, there are certainly unique cases where being able to pick and choose between HTTP and HTTPS could come in handy.

I was running into a similar scenario as @Dsavid Gardner. My company uses a third party vendor to manage our store portion of our site, and that store resides on the subdomain "https://store.mysite.com". We have 15 years worth of video content, and our current video management vendor breaks when a video is embedded in an SSL. (I'm guessing it's pulling in resources from HTTP domains, but that's another problem for another day)

Sure, I could purchase an SSL and go through the process of debugging two, third-party vendors, as well as doing a search and replace on our entire database (or an .htaccess file hack, but I digress) to correct any HTTP resource links, just to be able to have a message in the header say "Welcome 'YourName'", but that just seems like overkill.

Here's a simple Javascript solution that I came up with that sets a site-wide, insecure cookie based off of the secure cookies that are already set.

First, I grabbed some javascript cookie functions. Go ahead and put this code in the secure portion of your site:

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)===' ') { 
            c = c.substring(1,c.length);
        }
        if (c.indexOf(nameEQ) === 0) {
            return c.substring(nameEQ.length,c.length);
        }
    }
    return null;
 }
 function setCookie(cname, cvalue, exdays) {
    var d = new Date();
    d.setTime(d.getTime() + (exdays*24*60*60*1000));
    var expires = "expires="+d.toUTCString();

    /* Note, the W3 documents where I got this code didn't include the
    option to set the domain. I added this and it allows the cookie 
    to be shared across sub-domains. Be sure not to add "www" */
    document.cookie = cname + "=" + cvalue + "; " + expires + "; domain=.yourdomain.com";
 }
 /*Now we check our cookies on our secure server to find out if the user is
 logged in or not. In my case, the First Name is stored as a cookie. */
 var firstNameCookie = readCookie("the-secure-cookie-name");
 //
 if(!firstNameCookie){
    /* If the cookie doesn't exist, then the person isn't logged in. Add 
    conditional logic here if you'd like (such as deleting any current 
    logged in cookies from the HTTP portion of the site) */
 }
 else {
    /* otherwise, we have a successful login. By grabbing the cookie via 
    this javascript resting on the secure server, we haven't compromised our 
    security. However, if we set a cookie with javascript right now, it 
    won't be a secure cookie by default and we'll have access to it with 
    HTTP on the subdomain */
    setCookie("HTTPfirstName", firstNameCookie, 1.5);
 }

 */The clients first name is now accessible across subdomains in the cookie
  entitled "HTTPfirstName" */

In this instance, the only thing we've leaked over to our HTTP server is the client's first name. However, if you would like even more security, you could set your server settings to only allow certain cookies (i.e. "firstNameCookie) to be accessed by an HTTP request, and that adds an extra layer of protection. You can learn how to do that here

Sure, this isn't the most ideal solution. In the future, I plan to implement SSL site-wide, but having a simple javascript function to replace it in the meantime is sure nice to have.

Lucas
  • 314
  • 2
  • 5
  • 1
    Indeed, since I asked this practice has become very rare :) I'd suggest using a proxy in your case, which provides SSL access to outside but proxies internally as http to your existing video database. Then you can give users SSL'd connections whilst keeping your existing setup. You'd need to change the video backend logging (and possibly other IP-address-sensitive parts) to use X-Forwarded-For headers, but that's hopefully less work than fixing it fully to work with SSL? – David Gardner May 13 '16 at 20:25
  • Admittedly this depends on whether you're handing off users to elsewhere for the video content or if it goes through your server anyway... – David Gardner May 13 '16 at 20:25
  • 1
    Yeah, I understand that this is a very unique situation. I like the proxy idea, but the video delivery is done via Brightcove (A CDN and solely external resources) so I don't think that it would validate. I'm the sole developer for a large company, so unfortunately, site-wide SSL deployment ends up being a task that gets buried under quite a large list of things to do. A 10 minute javascript fix ended up being a great temporary solution for now, and hopefully someone else might find it useful as well. – Lucas May 15 '16 at 03:55