Sasha Romijn

Phishing out iOS URL schemes

In iOS, there are limited options to communicate with other apps. One of the most common choices is custom URL schemes. Like Safari picking up most links beginning with http:// or https:// (http(s) being the URL scheme in that case), opening a URL with the facetime scheme starts a FaceTime call.

Many third party apps that want to offer integration into their app do this with URL schemes. There are several lists of apps and their URL schemes. Using URL schemes is a good choice. It’s officially supported, and it’s trivial to integrate into an app. If I would want to open the Schiphol Airport venue in the Foursquare app, I would do:

UIApplication *app = [UIApplication sharedApplication];
NSString *path = @"foursquare://venues/4a84e798f964a520defd1fe3";
NSURL *url = [NSURL URLWithString:path];
[app openURL:url];

URL schemes are just like normal links, so you can also include them in a website. If you have Foursquare installed and are reading from iOS, this link should open the app, showing Schiphol Airport.

As a developer, it’s simple to register a URL scheme as well. There is no registration required with Apple. All you have to do is declare it in your Info.plist:

Now, hold on there: I’m not actually the maintainer of the foursquare app. What happens when both their app and mine claim to respond to foursquare://, and both are installed on a user’s device? Apple writes:

In other words, nobody knows. This is one of the critical issues to realise when doing anything regarding URL schemes: there is no guarantee which app will receive the data from the URL. Never ever send sensitive information by URL scheme.

From the other side, you also can’t trust the caller of the URL. You don’t know whether this is an intentional user action, or a sneaky app trying to trick the user into performing an action. If you do anything sensitive, like deleting data or placing a call, always ask the user for another confirmation from your app.

Phishing for your password

I just switched to 1Password – if you’re fast, you can still get it with the 50% heartbleed discount. It also supports a URL scheme: onepassword://. Because you can’t trust the caller of a URL, the only action you can perform with this, according to the documentation, is showing the 1Password app with a search filled in. That should be quite safe.

If you have 1Password installed, and click this Twitter search link, you may first be asked to unlock your vault:

And then you get the search results for Twitter:

Hold on there – did you just unlock your vault? What is that app that you just entered your master password in? As Apple documented, if multiple apps on your device registered the onepassword scheme, there is no process for determining what happens. Even if I have no malicious intent with getting you to open that link, you haven’t checked which app just opened and asked for your master password. The screen may have looked like 1Password, but that’s simple for anyone to fake.

Is this a practical attack?

Even with the master password you still need access to the password store on the device to make this a worthwhile attack against 1Password. The sandbox prevents you from taking another app’s data – you’d need another attack for that. However, if there were some way for an attacker to obtain your password store, the master password is typically the hardest item for them to obtain. This is why a breach at Dropbox, if you use that for syncing, does not immediately compromise all these passwords. There are probably cases where knowing the master password is very valuable.

This does mean there is an important difference, if you did just enter your master password into a malicious application: it would probably not be able to show you your actual passwords. However, there’s a fair chance that users will brush this off as a bug, and proceed in some other way. Actually, that second screenshot already shows a bug in the display of table section headers.

Is 1Password to blame? What about other apps?

1Password is definitely not to blame. I just used it as an example of a case where it’s easy to understand how this kind of phishing attack could be performed, but this could be exploited against many apps. For any apps that use logins, you could show a fake login screen for the target app, with the user assuming that they had been logged out. In fact, because you can register many URL schemes, you could have Flappy Capybara perform phishing attacks on many different apps at the same time. And they would keep working as long as the app is installed on the device.

How would someone get this into the App Store?

My approach would be to make some app, let’s call it Flappy Capybara, a free download which seems entirely innocent. None of the phishing screens would actually be visible unless Flappy Capybara was responding to the onepassword:// URL.

Wouldn’t Apple catch this in their strict review? I haven’t tried, because if I succeed, that’s a violation of my agreements with Apple. But, I highly doubt their review would catch this. The manual review isn’t all that thorough, and this seems very difficult to detect with static analysis.

What can we do?

The permanent solution would be for Apple to enforce registration and uniqueness of URL schemes. You can have as many as you want, but only the first to register can use a scheme.

If you develop an app that registers URL schemes that might be sensitive to a phishing attack, I think there’s little you can do. But for the user, there is one place where the phishing attack might be revealed: the app switcher, opened by double tapping the home button:

This shows the app icon and name, exactly as visible on the home screen. It is entirely plausible for me to sneak an app through the store and on user’s phones that has some hidden URL scheme responses, but only if the name and icon match its apparent purpose. I don’t think I would manage to do that if I also copy the 1Password name and icon. Either Apple will catch it, or it will look incredibly suspicious to users from the start.

In other words, to get this phishing app installed, it would actually have to be called Flappy Capybara with a fitting icon. And that means that after clicking a URL which should take you into 1Password, you can check the app switcher to see if the name and icon match. Flappy Capybara might be able to make the screen look like the real 1Password master unlock screen, but you’ll see its own name and icon in the switcher.

Further reading

If you’re going to implement URL schemes in your app, also have a look at x-callback-url, which aims to standarise this better.

From this blog, you may also like: