Übersicht Remote Code Execution, Spotify takeover

on the security implications of locally hosted web services

I try to bring this up whenever I have the chance to talk about application security architecture: the way we think about networks as boundaries is useful, but inadequate in 2018 and this has serious implications for how we design our apps.

The unfortunate poster child I’m using to contextualise this is übersicht, a MacOS widget host similar in use to Windows’s Rainmeter (anyone else remember putting that on their desktop in, like 2007?).

Übersicht like many applications these days is essentially a web browser running web apps with special privileges. One of these privileges is being able to run commands on your computer. Webapp widgets are run on a locally hosted website only accessible by the user’s computer. I’m sorry. I just got word this article is about Spotify too. Let’s pause for a moment and talk about that.

this blew my mind in 2007

I ⧸ Spotify’s All Singing, All Dancing Musical Backdoor

It’s quite common to see applications, like übersicht run web servers for local systems to access — Spotify, Steam and others all do this.

Often, these web servers offer the ability for websites to access functionality not normally accessible to the web. Spotify, for example runs a local web server that allows websites like Twitter and others to embed widgets which, when clicked send a message to your computer to play music on your computer. That’s weird, right? Even when you close the tab the music is still playing.

Let’s quickly dissect how this works. We can use this amusing proof of concept I made way back in August 2016 that plays a rickroll you can’t close without opening Spotify desktop:

Ok, so we have a big black space with a button, and if you click it, it makes your Spotify account play the Rick Astley classic from whatever device is currently supposed to play music (might even be your fancy wi-fi speakers). NB: this was fixed at some point

What’s this, though? When you hover over the face it says ‘play’…

If we inspect this element my ruse is immediately uncovered. It’s an iframe embedding open.spotify.com with the opacity set to 0.05 so we can barely see it. Let’s crank that back up.

Alright, we see the play button, but where’s everything else? Ha! Got you again. I cleverly used elements and border radiuses to crop the embedded Spotify player. Let’s reverse that too.

And there we have it! The man himself, smoldering through our LCD screens. But here’s the real question. How does a web page send commands to my Spotify?

Well, while I’d love to show you how it worked, it no longer works, so you’ll have to take my word for it. The player sent a request to a mysterious spotilocal.com with a Spotify authorization token that said ‘please play Rick Astley’. Spotilocal.com now points exactly nowhere, but as noted in this medium post from 2014, it used to point exactly at 127.0.0.1, which is IP address speak for ‘whoever is asking’ i.e. your computer.

But here’s the thing I found odd as a security engineer: if Twitter.com is able to make a request to spotilocal.com without triggering a mixed-content warning, it means my connection to spotilocal.com must be encrypted. But… how? And encrypted in transit from me to me? Call me Alice. Take my hand. Join me down this rabbit hole.

Are you ready? Take a deep breath. Encryption on the internet by giving each website a secret key. Only spotify.com knows spotify’s key, so only spotify.com can encrypt data like spotify.com can. Got that? Spotify.

In an incredibly mind-bending security trick, Spotify actually gives every single Spotify user in the entire world a secret key that allows them to attest to the undeniable fact that they, themselves are spotilocal.com. How do I know? I dumped it out of the Spotify program and — following some shenanigans with Spotify security I’ll mention later — posted it online!

Isn’t it a bad idea to give a private certificate for a domain to essentially everyone? I thought so too, and I pondered it, and I reported it to Spotify.com’s security team way back. Way, waaay back. Just before I posted the certificate online, actually.

What I told Spotify Security is what I will tell you now, dear reader: DNS is not to be trusted.

Why do we have certificates and all that in the first place? Well, a big part of that is that DNS is totally unencrypted. Anyone between you and the correct Spotify DNS server that so desperately wants to tell you spotilocal.com is 127.0.0.1 can tell your computer spotify.com is anything else. That includes the notorious scam site evil.com which steals your credit card details, identity and goldfish by your simply visiting it.

It actually happens all the time, and it’s definitely happened to you. When you go to an internet café, or Starbucks, or take your transatlantic flight to San Francisco or whatever and connect to the Wi-Fi, it hijacks DNS to tell your computer that any website you visit is the site you need to visit to log-on to the Wi-Fi. This is a terrifying dark incantation called in whispers — by some — Captive Portal.

e-excquse me…. pwease log onto our wifi uwu

“Why isn’t this a huge deal?” I hear your brain turning over and over, sleepless, comfortless in this knowledge. There’s a couple of reasons. If the website is encrypted, then even though you can send back a response as google.com, you can’t send back one that can be verified as google.com.

There’s an extra spanner in the works, though: how does your instance of internet explorer six know that we should reject unencrypted traffic claiming to be google.com when so many websites online are unencrypted?

That’s solved by a little thing called HSTS, which basically means when you load google.com it says ‘OK, here I am. I’m google and don’t let anyone else try to pretend to be me by accessing me over an insecure connection, you hear me?’

If you’re not a security anorak, I’ll add in one more security gem to blow your mind: anyone can be the ‘Free Starbucks Wi-Fi’. There’s literally no control on that. When your phone or computer connects to Starbucks, it just looks for networks called ‘Free Starbucks Wi-Fi’, and leaves it at that.

So, let’s say, just as a hypothetical I sit down in a Starbucks one day with a terrifying fruit of cyber-warfare: the WiFi Pineapple®. I can tell everyone in Starbucks that, actually, I’m the starbucks WiFi, connect to me please and they’ll be none the wiser. Then, I can see all their unencrypted internet browsing habits.

this is literally how they advertised the WiFi Pineapple® at DEFCON. my industry is very weird

Taking this a step further and using it to take over coffee goers’ Facebook sessions and others was the concept that underpinned the Firesheep software that I believe quite literally changed the world by making people wake up and realise an unencrypted internet is garbage.

In 2018 though, not a lot of user’s web browsing is unencrypted. I’m not an accountable enough writer to look up good statistics for this, but consider this: most people use google, facebook, apple, twitter, instagram, snapchat and little else. All these internet 1%ers are super likely to deploy really good encryption. I don’t have any statistics on that, you’ll just have to trust me.

Nevermind, we have the numbers:

Anyway. We can’t really get what we want. Whatever DEFCON goers want to believe, nobody’s going to drop a multi million dollar 0day vulnerability to bypass these defenses on you specifically just because they feel like it. I know I’m asking for it next DEFCON, but please. Think of the children.

I hope you didn’t get as side-tracked as me, because if you didn’t you’ll remember that we still have the spotilocal.com certificate on hand, so we can view any information sent to it. ‘But the connection to spotilocal.com goes to 127.0.01! That’s my own computer! It never goes to the outside internet!’ you whine inanely like an out of tune violin. Ah, my sweet summer child.

Before your computer even considers loading information from spotilocal.com, it first makes a DNS query up to the internet asking where the hell spotilocal.com is. And we, using our WiFi Pineapple® are DNS gods. We can say whatever we want, and we’ll say like, ‘you know what? spotilocal.com? it’s me actually.’

Now we can see whatever goes to spotilocal.com for every Spotify user that sends a request to it, and that means we get their Spotify OAuth token. Now I actually have no idea what the Spotify OAuth token lets you have access to. It could be a ton of really bad stuff. I don’t know. I never found out. But I do know something it can do, and that’s play music on a user’s system.

Let’s take a quick step back here to talk more about this secret token and what it probably lets me do. These tokens are used to enable access to certain resources or capabilities, in this case allowing the bearer to play music on your computer.

Almost always, when a company generates a token for itself, like Spotify generating a token to Spotify it has access to everything. Because, I mean, why would Spotify ever try to prevent Spotify from doing something? Spotify probably has your home address and favourite ice-cream flavour in a database somewhere. Spotify. But I can’t prove that, so let’s roll with the playing music thing.

So, let’s hypothetically say we don’t just already have full user access by getting this token and we want to play music on someone’s Spotify. How do we do that? The server’s on their computer…

Actually, we don’t even need DNS for this one. We can do the same as the embedded Spotify player does and send a request inside the victim’s browser to their local Spotify control server. We don’t even need to be Spotify. Authenticated requests between websites are fine. That’s something the internet just allows (with several extremely technical and complicated caveats).

What did Spotify Security say? That it’s a product decision and they’re fine with it. I tried to explain further but they confirmed, yes it’s a product decision and they’re fine with it. I’m also, to be fair, fine with posting the spotilocal.com certificate online. So I did. Well it’s removed now, so guess it wasn’t a product decision they wanted to keep WINKING EMOJI

This is actually something I deal with a lot, and I usually manage to convince people that what I’m saying is important. Not in this case, but, to quote a friend, my 0days are ‘always weird’.

II ⧸ The Übersicht RCE

First, let’s talk about what an RCE is, because judging by the coverage of software that get RCEs, most people don’t get it. An RCE is a ‘remote code execution’: it means, in a phrase, that I now have control over your computer. For a desktop computer this means your internet history, your video game high scores, your passwords, emails, everything. I now control it. You are, as they say in information security parlance — owned. In this case, by your cool desktop.

Where was I on Übersicht, anyway? (I’m copying and pasting the umlaut every time)

It makes these super cute little beautifully rendered desktop widgets, like the clock above by running a special webpage that contains all the web code you give it. This service is at the address 127.0.0.1:41416. That’s the ip address 127.0.0.1 (a special one saying ‘me’), and the port 41416 (that’s just something that identifies this server specifically).

Aside: I’ve been saying all this time that 127.0.0.1 means ‘me’. And it does, but it’s a specific kind of ‘me’. There’s also 0.0.0.0, which also kinda means ‘me’. The difference is that 0.0.0.0 kinda represents the public version of you that your computer presents to everything else on the network. If you host your website on 0.0.0.0:80, everyone else on your network can (probably) visit your hot new website. If you host it on 127.0.0.1, only you can (in theory) see it.

The point I’m trying to make with yet another aside is that if you put your dangerous web service that runs programs on your computer on 0.0.0.0 you’re slightly more screwed because everyone on your network can both see, and make requests to your bespoke foot-gun service.

When you load 127.0.0.1:41416 you actually get the Übersicht interface that’s drawn to your desktop. It feels a little weird the first time you do it.