📜 ⬆️ ⬇️

OAuth security in the era of mobile applications, or what the Internet is silent about

image

“The VKontakte API uses the open OAuth 2.0 protocol to obtain the access key. At the same time, the user does not transfer the login and password to the application, therefore his account cannot be compromised ” - VK API documentation .

“OAuth is an open protocol that provides a simple and secure authentication method for mobile, desktop and web applications” is a free translation of the slogan oauth.net .
')
Unfortunately, in many cases these statements are false. How to make work through OAuth more secure, both in terms of the end user, and when implementing your own OAuth provider, read under the cat. Such aspects of safety will be considered, which are currently paid unfairly little attention in open publications.

The material is saturated with specific terminology and is designed for a prepared reader.

From the author


The author is not an expert in the field of information security and does not claim to be 100% correct. The essay is written with a view to arousing in the reader a healthy curiosity and critical attitude towards the technologies used and their applicability areas, than in an attempt to kindle the flames of war with some established paradigm. All of the following in one degree or another is true for other similar protocols and ways to control access to the public API.

Historical background


We live in an era of rapidly developing technologies. Getting something new at our disposal, we begin to actively exploit it, push the limits of applicability, solve increasingly complex and diverse tasks, often guided by the method of cognition from the series: “It works and it’s okay”, “It helped me to solve that problem, it means will help with this "," A lot of people use it, it means it is good. " This approach is natural, as it works in most situations and allows you to get results without spending an excessive amount of time and effort, especially in the case when the result of our work will be used by a small number of people, and if the cost of the error is low. One of the technologies whose use has been extended in this way, in my opinion, is OAuth.

First, a little history: if you believe Wikipedia, the work on the protocol began in November 2006, and OAuth version 1.0 was approved on December 4, 2007. That was the time when Firefox began to cram Internet Explorer thoroughly, not only on the computers of web developers and Internet geeks, but also on ordinary people's machines; Facebook became available to all Internet users, VKontakte appeared, and Gmail opened registration without invites; Mobile Internet was slow, and smartphones were uncommon. Thus, the developers of the OAuth standard naturally believed that the browser is a secure, trusted, and only way for a user to access Internet resources. Responsibility for the power of attorney and browser security was assigned to the user (in the form of the need to install updates and tracking the absence of viruses on the PC) and developers (in the form of the need to deliver these same updates). Such a system was relevant and worked quite well until another technology leap occurred: in June 2007 the first iPhone went on sale, then in September 2008 the first version of the Android OS came out.

User security


Why does the entry into the market (or rather, the ubiquitous distribution) of mobile platforms make the assumption of browser proxy irrelevant?

Mobile platform developers have provided programmers with ample opportunities for writing applications, including free access to the TCP / IP stack. As a result, the user can no longer be sure where he actually enters his username and password, there is no way for him to know if this web form is really open from the desired web site (if webView is used, for example), keystrokes or entered data by an unscrupulous application developer. Moreover, developers of mobile platforms, reluctantly expanding the API for embedded browsers, only exacerbate this state of affairs.

It can be argued that the user needs to be careful, it is not necessary to enter the login and password from your social network in the first counter application you installed from the market, even if the password entry form looks like real. And in general, if you are asked for a password, this is a clear sign that something is wrong, because an honest application will certainly use the SDK for authorization of the corresponding social network. But in practice, users are so accustomed to the “Login with VKontakte” and “Login with Facebook” buttons in their browsers, which will not embarrass them if the corresponding button in the application shows a correspondingly looking form for entering the login and password. Even though they will painfully remember the once long-changed and once or twice entered password. Thus, the problem of phishing, which was acute enough for OAuth even when used through browsers, rises to a whole new level.

So what do OAuth developers tell us? In OAuth 2.0, which was released in October 2012, there is not a word about mobile applications. In the preliminary version of the document called OAuth 2.0 for Native Apps, which appeared only in February 2016, application developers and OAuth providers are invited to try to make sure that the user doesn’t have to often enter a password or show some information related to the account from which it was logged in. . In this way, the user will be able to suspect that something is wrong in the case of a malicious application.

On the other hand, all major OAuth providers in one form or another provide an SDK for mobile applications, which allows you to authorize the user through the provider application, and not through OAuth. At first glance, everything is fine, but if the user is not authorized in the provider’s application, it is suggested to enter the login and password, and if the provider’s application is not installed, the SDK will most likely start the OAuth authorization already familiar to us, which in turn provides new field of activity for phishing.

Despite these problems, a knowledgeable user of Internet services is not so bad if you follow a simple rule: enter your password and login only on the website or the OAuth application of the provider and only if the user got there independently, and not automatically. Yes, and all this in addition to updates, control of installed software and, in some cases, antivirus.

OAuth provider issues


Everything becomes much more interesting if we ourselves want to become (or are already) an OAuth provider. Suppose we have implemented the Authorization code flow and the API is used only for controlled services - everything seems to be okay for now. Then there was the need to make access for external services: “Of course, no problem, because OAuth is intended for this, isn't it?” We think. But then the thought creeps in: what specific external services will they use us? What if these services are actually mobile applications? How can applications guarantee the security of their client_id and client_secret? How, then, will we be able to find out if any malicious application is pretending to be completely harmless and on its behalf creates all sorts of disgraces?

Unfortunately, OAuth2 does not provide an answer to this question, only paragraph 10.1 of RFC6749 says that it is forbidden (!!!) to use a password (this is about client_secret) to authenticate OAuth clients implemented as mobile or client applications, except the case when this password (and the unique client_id) is issued separately for each specific installation of the application on the user device (but we are hardly interested in such a case). The “OAuth for mobile clients” Draft only starting from March 2, 2017 ( paragraphs 8.8, 8.9 ) suggests using App-claimed HTTPS URI Redirection, but does not mean that the secure version of this approach is available only for iOS 8, Android 6.0 and above . This approach, although it protects the user from malicious applications, does not in any way help the OAuth provider detect the malicious client that has taken over the client_id. At the same time, the standard does not give any recommendations on how our provider implementation will distinguish mobile applications from server ones. Those. in fact, client_secret security is entirely in the hands of the client, which may be beyond our control.

Well, since the standard is not an assistant for us, we will use our own common sense. Suppose we only need to allow server applications - everything is relatively simple: you need to attach an IP address (or several) to each client_id from which it can send requests for receiving a token. You can even provide a user interface to populate this list; the main thing is to ensure that there are not too many of these addresses. And then somebody will enter the whole subnet of some hosting provider, and forgive-bye all security: it will be enough for an attacker to settle with a client in one data center.

Well, what to do if you still need to provide access to mobile applications? If the use of our service implies a fee and the application is under our control, then you can use the account mechanism provided by the AppStore and the Play Market after the purchase is made. These accounts contain the application's Bundle ID, are tied to a specific user and can be checked on the server side by sending a request to Apple or Google. An account check can be associated, for example, with an access or refresh token update.

If our service is free, this method may not be suitable: in spite of the fact that you can make a “free” purchase, the user of the application will have to enter the data of his bank card. Also, this method will not work if the mobile application does not belong to us: platform developers do not provide mechanisms for controlling purchases in third-party applications.

In the case when the circle of users of our application is well known to us (for example, employees of the enterprise) and controlled, then client certificates can be used to authorize the client. On the other hand, if the enterprise actively uses user certificates, then access control to the API will probably be more convenient to implement on the basis of TLS, rather than implement its own OAuth extension.

If, after all, the range of users of the application is wide enough, and we do not want to force users to make purchases and enter their card details? Some time ago we had only one possibility: obfuscation of the client_id (client_secret) in our application and the difficulty of intercepting unencrypted traffic in the OS network stack. The hacking-resistant implementation of such a task requires both a high level of specialist training and time consuming; and thus virtually unavailable for small companies and freelance programmers.

Fortunately, starting from some point, Google provides SafetyNet service, which allows you to find out the key imprint with which the application was signed, as well as its Bundle ID and check this data on the server side (alas, when checking the service’s performance, it was not possible to get an answer different from {"isValidSignature": false}). This API is supplied as part of Google Play Services and, theoretically, is available starting from Android 2.3, provided the Play services are updated.

It remains an open question whether SafetyNet allows you to check application data published by other developers, and therefore can we use it to control access to our API from other applications? The documentation does not give an explicit answer to this question, but is written in a key that does not imply such a scenario. Also, Google Play Services is not available for all countries and may not be available on phones from Chinese manufacturers.

Unfortunately, Apple does not provide similar services to date. But in any case, this is a big step forward, and in some cases, using SafetyNet may be more convenient than other mechanisms for authentication of client devices.

What to do if none of the proposed options does not suit us? Then we, as developers of the public API, will have to keep in mind that we cannot reliably distinguish between client applications, and the user actually has no control over which API resources to which applications he provides. That is, we cannot rely on the concepts of scope and client_id from OAuth, which is about half the capabilities provided by the protocol. Or, if there is enough competence and resources, we can implement on the server side any heuristic algorithms to identify queries with a fake client_id.

I hope that the large OAuth providers use one of the last two (the others impose too stringent restrictions), the ways of avoiding OAuth problems proposed here. Indirectly, this can be indicated for example by the fact that previously VKontakte gave access to the user's email only to certain trusted applications , now such a request is included in the public API .

Total


From the above, we can conclude that OAuth is in fact very far from the level of security that we are used to imply, using such industrial technologies as TLS or SSH. When implementing an OAuth provider, you must carefully weigh the benefits of its implementation and all potential security problems. It also requires the implementation of suitable workarounds for the problems described above, since none of the libraries known to the author for popular web frameworks takes them into account. To access the API from mobile applications, it may make sense to develop your own SDK using the most user-friendly methods for interacting with OAuth.

The author thanks his friends and colleagues for constructive comments and assistance in preparing this material and separately - Sergey McKenna for his help in exploring the features of the Apple iOS SDK.

The OAuth logo is designed by Chris Messina and is distributed under a Creative Commons Attribution ShareAlike 3.0 license.

UPD 11.05.2017 : Apparently, there is another vector of phishing attacks for OAuth, which is quite difficult to prevent: the introduction of the authorization page into the RIA interface. This may indicate a recent successful attack on users of GMail .

UPD 05/13/2017 : Google continues to attempt to combat OAuth phishing by blocking the opening of its OAuth authorization pages through WebView . In my opinion, this is just a half-measure, since the UserAgent header can still be rewritten by an attacker. You can also simulate other distinctive features of browsers.

Source: https://habr.com/ru/post/320744/


All Articles