OAuth is a fantastic login protocol that allows disparate web applications to all use the same login provider. However, I’ve discovered that its use in native mobile applications is borderline dangerous, and in this post I’ll describe why.
Last year I released my first (and still only) iPhone application. Even though my app doesn’t use OAuth, the then recent Twitter/OAuth fiasco stoked my interested in mobile OAuth. I was particularly curious how OAuth providers protected their passwords in their mobile SDKs.
I downloaded the Facebook SDK and poked around in the iPhone simulator, and frankly I didn’t like what I saw. In less than an afternoon, I was able to build an app that could steal a user’s password as they logged in through Facebook Connect, all 100% transparent to the user, 100% transparent to Facebook, and 100% transparent to Apple. In a word, this is not a good sign for OAuth and native mobile apps. To be clear, this affects every single OAuth provider and mobile platform, not just Facebook and iOS.
Despite numerous web searches, emails, and even code submission to Facebook, I haven’t seen anyone talk about this problem on the web at all. Seeing as how the Facebook Connect SDK is almost 2 years old, and many other companies are following suit with OAuth in native mobile SDKs, I think this conversation is long overdue.
In this post, I’m going to explain how and why OAuth in native mobile apps does not secure your password, and why you should still be wary when logging into Facebook/Twitter/Google/anything through any app except their respective official native mobile apps. I’m writing this post to expose the still weak security for single sign on services in native mobile apps. I am not providing any source code, though after reading this post I’m sure you’ll agree that eavesdropping on an OAuth transaction in a native mobile app is extremely easy even for a novice programmer.
The purpose of Oauth is to let application developers use Twitter/Facebook/anysite’s login mechanism, all while keeping the password 100% secret from the application developer. In this world, if the application turns out to be an untrusted malicious application, all the user needs to do is turn off access from that application on Twitter/Facebook/anysite’s settings page.
However, native mobile application developers are still able to access (steal) your password even when using OAuth for login, all 100% undetected. This means that for native mobile apps, using OAuth is not any more secure than using Basic Auth, and Twitter’s API change from Basic Auth to OAuth does nothing to protect user’s passwords from malicious application developers.
To be clear, this affects every OAuth implementation in native mobile apps, across iOS, Android, and [I believe] Windows 7.
When your password is safe: Web Apps
As our first example, let’s take a look at web apps – this is true for both mobile web apps and desktop web apps.
OAuth succeeds in protecting the user’s login information because the web browser is a 100% trusted agent and ensures that the application code on the web app’s domain name cannot access any information on the OAuth providers domain name. This is called Same Origin Policy.
For example, when [insert malicious web app here] begins an OAuth login, the browser opens a window/redirects/iframes to the authentication provider (probably Facebook, Twitter, Google, etc). Due to the browser’s security, it is impossible for the malicious app to eavesdrop as the user types in their password. After the user enters their username + password into the legitimate login screen, approves (or disapproves) the web app from accessing it’s account, and is then redirected back to the potentially malicious web app.
At no point in this transaction does the malicious web app have access to the user’s login credentials. Browser security prevents any scripts on the malicious site from interfering/listening to/intercepting the login credentials. It’s this trusted and neutral 3rd party browser that makes this negotiation possible. The phone’s built in browser acts as the trusted middleman during the OAuth transaction.
Once the user discovers the malicious apps evil plot, all the user needs to do is login to the OAuth provider’s trusted site and remove the malicious app from their trusted apps. done.
You’re safe, the world is happy, and OAuth saves the day. Not so in native mobile apps, let’s take a look:
When your password is not safe: Native Mobile Apps
In native mobile apps, the mobile application itself takes the place of the browser, so there is no longer a trusted neutral 3rd party browser to act as the trusted middle man in OAuth transactions – the mobile app itself acts as both the OAuth client and the OAuth middle man!
So what does this mean? It means any native mobile app implementing OAuth can steal your login credentials, completely transparent to you the user, the OAuth provider, and even the phone manufacturer/carrier.
Since the mobile app hosts a tiny instance of the web browser inside of itself, that app can see/do/act on anything inside the web content it shows – no exceptions. This means the Same Origin Policy we discussed above is now out the window. Even though the native app uses WebKit to do the rendering/browsing, that native app can also do absolutely anything to any webpage loaded inside of it, including stealing passwords, without the loaded website even knowing.
I’m not going to show any code, but I’ve verified in code that this is in fact possible. I’ve effectively stolen my own Facebook password using Facebook’s provided iOS OAuth library. It only took minor modifications using entirely publicly available APIs in iOS. The exact same attack could be used in any app that logins with Twitter, and is not specific to iOS – this affects Android (and presumably Windows 7 though I haven’t looked at their API).
How the attack works:
- Malicious attacker builds native mobile app and uses any publicly available OAuth SDK from Facebook/Twitter/anyone
- The attacker loads the legitimate OAuth login screen using a web view available from the phone’s public SDK
- User authenticates, and OAuth transaction is completed as normal – except the malicious app has been listening to every keystroke! Password: compromised!
- Malicious app uploads credentials to anonymous server in China
This is all because the embedded browser in native applications cannot be the trusted middleman in the OAuth handshake.
Mobile Web: 1, Mobile Native: 0
Currently, the only secure way for OAuth to exist in mobile is for mobile web applications. These applications still run in a trusted 3rd party browser that prevents cross domain script execution. Since mobile native apps fill the role of OAuth client and trusted browser, the user’s login credentials are not secure.
It should be noted that OAuth’s website makes no mention of using OAuth for native mobile apps, but clearly mobile app developers are still using it to solve the elusive secure authentication problem.
Again, this affects 100% of OAuth implementations in native mobile applications, regardless of OAuth provider or mobile platform.
For a long time, Twitter provided only basic auth for it’s API, but its more recent OAuth API isn’t actually any more secure. I believe that the only way to allow secure OAuth within native mobile apps is to have a more strict web browser API for native app developers, and to properly notify OAuth providers when their service is being accessed from an insecure mobile browser. Unfortunately the safest solution right now: don’t use OAuth.
I’m not sure what the correct long term solution is for login in native mobile apps, but OAuth currently falls very short. Mobile still has a long way to go to keep users passwords and data safe.
17 thoughts on “Stealing Passwords is Easy in Native Mobile Apps Despite OAuth”
Umm, so, to summarize, don’t type your password into an untrusted application. Thanks for that brilliant piece of advice.
Right, you can’t say “this application is untrusted” and then embed a browser into it and pretend you can trust the browser while not trusting the application.
So what you’d want to do is use another flow where the app says “hey, go to this URL in your trusted browser”, and the provider shows a short, temporary request token to a callback URL, or, if necessary, that the user types in.
But there’s no incentive for an app developer to do it that way, and lots of disincentive.
@Tim, the promise of OAuth is that you can login to any application, trusted or not, and still be safe. That’s the expectation of users/devs/providers and it’s simply not true.
@Kevin, exactly right. and it’s a terrible user experience to kick the user from the mobile app to the mobile browser and back again.
The same is true of any native app. If I download an application and install it on my PC and it pretends to use OAuth then of course it can get my password.
If someone created a web browser called SpyHackBrowser and I installed it then that web browser could just as easily intercept every single key stroke I ever make and take all my passwords to everything.
“@Tim, the promise of OAuth is that you can login to any application, trusted or not, and still be safe. That’s the expectation of users/devs/providers and it’s simply not true.”
Correction: the promise of OAuth is that you can login to any *website*, trusted or not, and still be safe. Native applications on any platform are fundamentally different from web applications.
@Iain: I haven’t been following OAuth’s more recent developments, but IIRC, this certainly was one of the use cases on the table in the initial phases of the specification.
And here you’re *still* accessing a website, but it’s the native app doing it on your behalf, rather than a webapp or the browser acting as a user-agent.
So, like OpenID, here you have a wire protocol that’s basically sound, but really needs tighter integration between the infrastructure on the client side and the provider to get a good user experience. And, like OpenID, OAuth providers have the *option* of authenticating you with something you can’t sniff and replay (Phone Factor seems like an especially good method for apps on phone platforms), but they don’t, because even after things like the Gawker leak, you basically don’t care if anyone steals your password.
(Not that I’m bitter or anything.)
with iOS SDK, UIWebView acts just like a browser, so it does have the same origin policy. Can you please share code to proof your concept?
In the above steps:
So what you are saying is that if this is possible, then any native app irrespective of whether u use oauth or not, passwords can be stolen using the webview. I will confirm this soon on android. Hence Manufacturers of Phones should provide a protection scheme for password/input fields on webviews!eg Listeners/events should be well defined for this field, if not avoided.It also cautions Androids Openness to webview.
@mistaguy, that’s exactly right. a native application can steal absolutely any data out of a UIWebView including passwords.
I think this is an especially bad thing for OAuth, since users will assume that OAuth logins are especially secure since they are so official looking – loading the host website and all
@Adam Wulf good then.Since there is no solution as of now, i have kind of thought of widget based option for other Developers for an API platform .the way this operates is that Developers are provided with a library that they use for creating apps that are install able to the Parent Native Mobile App.just like snaptu.such that all Oauth Password Stuff is handled securely and solely by the Parent app hence. Developers then just use interfaces in a library to create their widget based app to be installed on the Native Parent App. Hence a serious Warning must be availed on the website,etc for the users who sign up and especially those who root their android phones. If this widget based option security is handled well with proper cryptography
, then even a rooted use is still save. I will see how this works and if successful, i will github and blog. Otherwise thanks for the Post, i read it at the time when am creating an API
As a consumer this implies there is a risk of using oAuth if the application is from an un moderated app store. Did you ever try to submit your app to iTunes? I would expect / hope that they would run code scanning to detect these kind of security issues – but maybe I am being too hopeful.
Of course there is still a risk that moderation fails to spot these apps, but it is a small point of mitigation.
@Steve, that’s just the thing about this attack. Even with Apple’s moderated approval process, a static code analyzer won’t be able to detect this attack (especially b/c the attack uses 100% public APIs). Since the OAuth handshake completes normally, this attack would be completely invisible to the human reviewer as well, even if they were actively looking for it.
From the oauth rfc:
Standards Track (Page 52)
An embedded user-agent poses a security challenge because resource
owners are authenticating in an unidentified window without access
to the visual protections found in most external user-agents. An
embedded user-agent educates end-users to trust unidentified
requests for authentication (making phishing attacks easier to
Excerpt from this link…
OAuth 2.0 authorization requests from native apps should only be made
through external user-agents such as the system browser (including
via an in-app browser tab). This specification details the security
and usability reasons why this is the case, and how native apps and
authorization servers can implement this best practice.
The OAuth 2.0 [RFC6749] authorization framework, documents two
approaches in Section 9 for native apps to interact with the
authorization endpoint: via an embedded user-agent, or an external
This document recommends external user-agents like in-app browser
tabs as the only secure and usable choice for OAuth. It documents
how native apps can implement authorization flows with such agents,
and the additional requirements of authorization servers needed to
support such usage