Your login form posts to HTTPS, but you blew it when you loaded it over HTTP

Owner: “Ah, but it posts to HTTPS so your password is secure! We take security seriously. Our measures are robust.” (and other random, unquantifiable claims)

Loading login forms over HTTP renders any downstream transport layer security almost entirely useless. Rather than just tell you what’s wrong with this, let me show precisely why this is with a site that implements this pattern:

How’s that for simple?! What people forget about SSL is that it’s not about encryption. Well that’s one feature of secure sockets, another really essential one is integrity insofar as it gives us confidence that the website content hasn’t been manipulated. Anything you load over an HTTP connection can be easily changed by a man in the middle which is why it’s absolutely essential to load those login forms over a secure connection. OWASP is very specific about this in part 9 of their Top 10 web application security risks and summarise it well in the transport layer protection cheat sheet:

The initial login page, referred to as the "login landing page", must be served over TLS. Failure to utilize TLS for the login landing page allows an attacker to modify the login form action, causing the user's credentials to be posted to an arbitrary location.

It’s not just Woolworths doing this, in fact it’s extremely common and you’ll see it on GoDaddy:

I’m calling out these simply because they’re high-profile sites yet they all load the login forms over HTTP and post to HTTPS. Why aren’t they implementing SSL correctly? Most likely convenience; customers can login direct from the homepage and they can have it delivered over HTTP. Mind you Pandora links off to a login page so why they couldn’t just serve that securely to begin with is a bit of a mystery.

So how should it be done? Load the login form over HTTPS, either by linking to a dedicated login page or popping it up in a separate window (although there’s a UX argument against this). Even better, just load the whole site over HTTPS! Yes, there are some barriers to HTTPS across the board (managing certs in web farms, dependencies on assets from third parties, impact on CDNs, etc) but it sure solves the login form issue. Check out Netflix’s approach – straight into HTTPS, job done!

The other issue with the examples above is that potential manipulation of the content aside, missing HTTPS on the login form leads to exactly the discussion this post opened with – users not believing their credentials are protected. All the messaging we’ve been delivering to website users since the early days of the web about checking for the padlock in the browser address bar goes down the drain because it’s simply not there! There’s no assurance that their credentials will be protected and it’s a real shame to dilute such an important security message.

As for how the exploit in the video works, it’s just a simple Fiddler script to inject the keylogger before the body tag closes off. The keylogger itself is over on Google Code, the only code I wrote to incorporate it was the script tags you saw at the end of the video and the “Hack Yourself” website which receives the logged keys. It really is that simple.

Whilst Fiddler is good for demonstration purposes, clearly an actual weaponised attack would work differently but the principle is the same: When unencrypted traffic passes through a node on the network – NIC, ethernet cable, router, proxy, ISP, etc. – it may be observed or manipulated by an attacker. This isn’t theoretical, there are many precedents such as the Tunisian government harvesting Facebook credentials en mass.

This is all a bit odd really, I mean these sites have gone to the effort of implementing some SSL but then blown it by loading those login forms over HTTP. As we saw with Woolworths, posting over a secure connection is completely useless if there’s no integrity in the login form itself, an attacker may already have the credentials by then if the connection is compromised which is the very risk they all implemented SSL to protect from in the first place!