HTTPS or SSL or TLS or whatever you want to call it can be a confusing beast. Some say it’s just about protecting your password and banking info whilst the packets are flying around the web but I’ve long said that SSL is not about encryption.
As an indication of how tricky the whole situation is, OWASP talks about insufficient transport layer security. Not “have you done it right” or “have you done it wrong”, rather have you considered all the little nuances that go into the correct implementation of this invaluable security feature.
Naturally, when this tweet from Mark Hemmings popped up on my timeline was a little intrigued:
We’ve all seen this before right? Clearly it means your valuable password is being sent over the wire in plain text and the ghosts in the wires will immediately harvest them and do frightful things with them, won’t they? Apparently not:
This is not your usual customer service rhetoric – these guys know about iFrames! They continue:
The key here is the word “key” in that sentence. Hang on – so other pages aren’t sent over secure connections? What happens if you’re already logged on?
This is a great opportunity to revisit the quirks of HTTPS because as it turns out, Mark is spot on and there are some very insufficient practices going on here. Let me break it down into 5 discrete problems and why each one of them undermines the HTTPS implementation not just on Top CashBack, but on many other sites following the same patterns.
Problem 1: Sending sensitive data over an insecure connection
Of course you can see where the problem begins right here:
That’s right, it’s a registration form loaded over HTTP. Before we even get to looking at the claim of the login being loaded over HTTPS, we’ve got a serious problem. This isn’t even one of those common misunderstandings along the lines of “Oh but it’s safe because it posts to HTTPS” because, well, it doesn’t (and it isn’t). Watch the HTTP request after completing the form and it looks like this:
POST http://www.topcashback.co.uk/light-box/join/ HTTP/1.1
And here’s the form variables in the request body:
Yes, that really is the password I created and yes, it really is sent from my PC through all the wires to their server in plain text. In fact after registering there were 140 requests made by the browser to load assets onto the page and some of them were made over HTTPS; one to Facebook, one to Google, one to Doubleclick but zero to Top CashBack!
Problem 2: Mixed mode
Moving on, after registering I was sent a verification email and I duly followed the link. Good news – it’s an HTTPS address! Bad news, it’s not secure:
Problem 3: Sending auth cookies over an insecure connection
Clearly we’re now logged on which gives us an opportunity to move onto the next problem. Let’s jump back to the homepage and you can immediately see the issue:
You see that?! Let me help: this page has been requested over HTTP but somehow it knows that I’m logged on as it’s able to display the “My account” and “Log out” links in the top right. How can it be?
Let’s take a step back and I’ll provide some context. HTTP is a stateless protocol which means that every time your browser makes a request it’s over a whole new connection with no implied continuity between them. This is problematic because it means that you can’t persist information across requests such as an identity and the fact that you’re logged in. To work around this limitation we have the cookie, those little bytes of data that are sent between client and server in request and response headers. When you log on to a website, it’s (almost always) a cookie which is sent to your browser in the response and then sent back to the server with each request to ensure it knows who you are and that you’re authenticated.
The problem is this: if someone else can get hold of that cookie then they can become you! This is called session hijacking and it involves nothing more than an attacker intercepting the cookie, setting in their own browser then voila – they’re you! This is what Firesheep did a few years back and caused such a fuss. It was arguably a significant factor in websites such as Facebook implementing HTTPS everywhere so that sessions couldn’t be hijacked in this fashion. In fact many websites got the message very quickly, but some did not…
This risk is easily verified as the HTTP request to the page above contained the following cookie:
Here, I’ll show you: I copied the cookie above, inserted it into a Chrome session using Edit This Cookie, loaded up the account details page and here’s what I now have:
That’s my details! In my “attacker mode” I never saw a password, all I needed was those few bytes from the cookie sent over the insecure connection and I’m in. There are many, many ways that an attacker can get the cookie from an insecure connection. One of the easiest is simply sniffing wireless traffic as I’ve previously demonstrated, then there the good old physical wiretap or simply observing the traffic through any of the legitimate nodes it passes through; router, gateway, ISP, etc.
Once you have the cookie, you have access to everything that an authenticated user can see. For example:
I’m sure Top CashBack probably feels they’re being secure by sending this over HTTPS (and certainly that’s a good thing in and of itself), but as an attacker, it doesn’t matter one bit because I’ve already hijacked the session when the cookie was sent insecurely. All the HTTPS on the page above does is allows the attacker to load the page securely!
Edit: I should clarify that authenticated users cannot see their own banking info and that any pre-existing accounts are obfuscated in the fields above.
Problem 4. Not marking auth cookies as “secure”
This is closely related to the previous point and it’s one I wrote about just last week in C is for cookie, H is for hacker – understanding HTTP only and Secure cookies. Let’s log back in again via Chrome and inspect that auth cookie we looked at earlier on. Here it is:
See that “Secure” option? Well obviously it isn’t! The problem this creates is it means the browser will happily send this cookie across an insecure connection and indeed that’s the problem we saw above when the page loaded over HTTP was able to recognise that we were authenticated. In this case I suspect it’s actually by design (which is even worse) as if the cookie was actually secure then you’d never be able to see your authenticated state reflected on those insecure pages.
Flagging a cookie as secure means that the browser simply will not send it over an insecure connection which is exactly what you want when we’re talking about auth cookies. All the HTTPS in the world won’t save you when there’s just one single inadvertent HTTP request which discloses the auth cookie and we saw earlier, this one simple mistake could mean disclosing serious data such as banking info.
Problem 5. Relying on HTTP to load login forms
It’s taken until the last point but let me get back to the original assertion about the login form being loaded over HTTPS. Firstly, we’ve already registered over HTTP and sent our password via an insecure channel then sent that auth cookie flying around in the clear so by now the value presented by HTTPS has pretty much been shot to pieces anyway. But let’s push on.
When you hit the login button you’re presented with this following:
You know it’s secure because it has a padlock bitmap and it says “SECURE LOGIN”, right?! What actually happens here is that the browser makes a separate request to this page containing the login form which is indeed requested over HTTPS. The question is how did the browser know to request that page? I’ll tell you how, the page we originally loaded – the one requested insecurely over HTTP – has the following markup in it:
<a class="login-toggle" href="#" title="Login" onclick="ToggleLogin('https://www.topcashback.co.uk/login?RedirectURL=http%3a%2f%2fwww.topcashback.co.uk%2fhome');return false;" ><span>Login</span></a>
The problem, of course, is that when you load a page over HTTP then there’s no protection against a man in the middle manipulating the contents of the page. For example, there’s nothing to stop an attacker from changing that login path to a website of their own, they could then easily replicate the login control layout and the victim would be none the wiser. Tampering of this kind is nothing new, in fact it’s something we’ve seen many times before including in the Tunisian government example I reference here.
So how does this differ to other more secure implementations? The main thing is that “none the wiser” bit; because the login page is loaded into an iframe there’s no ability for the user to see the certificate loaded into the browser, you know, the one that’s usually perfectly clear in the address bar:
In fact on that basis alone – the fact that the certificate can’t be seen – it means the implementation is relying on the user’s trust rather than explicitly showing them “Hey, here’s the HTTPS address and the certificate”. Without either of these the user can only draw the assumption that Mark did right back at the beginning which is that their credentials are being sent in plain text.
Norton secured (so it must be secure!)
One of the great ironies with this site is the “Norton Secured” logo down the bottom right hand corner:
This gives a very reassuring report of the site:
I’ve included this to make the point that whilst it may be reassuring, in this case it’s totally useless. The seal is on a page loaded over an HTTP address so in theory, it could have come from anywhere. But that aside, the whole assertion that a logo on a page implies some form of security when there are such blatant holes is a bit ludicrous.
The point with all the HTTPS in the Top CashBack site is simply this: it doesn’t matter how many pages you’re loading securely or how many padlock icons or vendor certifications you drop on the site, once you start sending auth cookies around insecurely, you’re toast. It’s completely pointless to secure those personal details in transit but then let the auth cookie which can load them back up float around in the clear. That is a very insufficient use of HTTPS indeed.
Update: Please also read the follow-up to this post titled 5 ways to tackle an insufficient HTTPS implementation which describes how each of the issues below has been subsequently remediated.