移动OAuth 2.0的安全性

image

Popularity of mobile applications continues to grow. So does OAuth 2.0 protocol on mobile apps. It's not enough to implement standard as is to make OAuth 2.0 protocol secure there. One needs to consider the specifics of mobile applications and apply some additional security mechanisms.

移动应用程序的受欢迎程度持续增长。 移动应用程序上的OAuth 2.0协议也是如此。 仅仅实现标准以使OAuth 2.0协议在那里安全是不够的。 人们需要考虑移动应用程序的细节,并应用一些其他安全机制。

In this article, I want to share the concepts of mobile OAuth 2.0 attacks and security mechanisms used to prevent such issues. Described concepts are not new but there is a lack of the structured information on this topic. The main aim of the article is to fill this gap.

在本文中,我想分享用于防止此类问题的移动OAuth 2.0攻击和安全机制的概念。 所描述的概念并不是新概念,但是缺少有关此主题的结构化信息。 本文的主要目的是填补这一空白。

OAuth 2.0的性质和目的 (OAuth 2.0 nature and purpose)

OAuth 2.0 is an authorization protocol that describes a way for a client service to gain a secure access to the user’s resources on a service provider. Thanks to OAuth 2.0, the user doesn’t need to enter his password outside the service provider: the whole process is reduced to clicking on «I agree to provide access to…» button.

OAuth 2.0是一种授权协议,它描述了客户端服务获得对服务提供商上用户资源的安全访问的方法。 借助OAuth 2.0,用户无需在服务提供商外部输入密码:整个过程简化为单击“我同意提供对…的访问”按钮。

A provider is a service that owns the user data and, by permission of the user, provides third party services (clients) with a secure access to this data. A client is an application that wants to get the user data stored by the provider.

提供者是拥有用户数据的服务,并且在用户许可下,向第三方服务(客户端)提供对此数据的安全访问。 客户端是想要获取提供者存储的用户数据的应用程序。

Soon after OAuth 2.0 protocol was released, it was adapted for authentication, even though, it wasn’t meant for that. Using OAuth 2.0 for authentication shifts an attack vector from the data stored at the service provider to the client service user accounts.

OAuth 2.0协议发布后不久,它就进行了身份验证 ,尽管它并不是为了实现此目的。 使用OAuth 2.0进行身份验证会将攻击向量从存储在服务提供商处的数据转移到客户端服务用户帐户。

But authentication was just a beginning. In times of mobile apps and conversion glorification, accessing an app with just one button sounded nice. Developers adapted OAuth 2.0 for mobile use. Of course, not many worried about mobile apps security and specifics: zap and into the production they went! Then again, OAuth 2.0 doesn’t work well outside of web applications: there are the same problems in both mobile and desktop apps.

但是身份验证只是一个开始。 在移动应用程序和对转换的赞美中,仅需一个按钮即可访问应用程序。 开发人员将OAuth 2.0修改为可移动使用。 当然,很少有人担心移动应用程序的安全性和特性:zap进入他们的生产! 再说一次,OAuth 2.0在Web应用程序之外无法正常运行:移动和桌面应用程序中都存在相同的问题。

So, let’s figure out how to make mobile OAuth 2.0 secure.

因此,让我们找出如何使移动OAuth 2.0安全。

它是如何工作的? (How does it work?)

There are two major mobile OAuth 2.0 security issues:

存在两个主要的移动OAuth 2.0安全问题:

  1. Untrusted client. Some mobile applications doesn’t have a backend for OAuth 2.0, so the client part of the protocol flow goes on the mobile device.

    不受信任的客户。 某些移动应用程序没有OAuth 2.0的后端,因此协议流的客户端部分在移动设备上进行。

  2. Redirections from a browser to a mobile app behave differently depending on the system settings, the order in which applications installed and other magic.

    从浏览器到移动应用程序的重定向行为会有所不同,具体取决于系统设置,应用程序的安装顺序和其他功能。

Let’s look in-depth at these issues.

让我们深入研究这些问题。

移动应用程序是公共客户端 (Mobile application is a public client)

To understand the roots and consequences of the first issue, let’s see how OAuth 2.0 works in case of server-to-server interaction and then compare it with OAuth 2.0 in case of client-to-server interaction.

为了了解第一个问题的根源和后果,让我们看看在服务器到服务器交互的情况下OAuth 2.0如何工作,然后在客户机到服务器交互的情况下将其与OAuth 2.0进行比较。

In both cases, it all starts with the client service registers on the provider service and receives client_id and,in some cases, client_secret. client_id is a public value, and it’s required for the client service identification as opposed to client_secret value, which is private. You can read more about the registration process in RFC 7591.

在这两种情况下,都以客户端服务在提供者服务上的注册开始,并接收client_id,在某些情况下为, client_secret. client_id , client_secret. client_id是一个公共值,它是客户端服务标识所必需的,而不是client_secret值(私有)。 您可以在RFC 7591中阅读有关注册过程的更多信息。

The scheme below shows the way OAuth 2.0 operates in case of server-to-server interaction.

以下方案显示了服务器到服务器交互时OAuth 2.0的运行方式。

Picture origin: https://tools.ietf.org/html/rfc6749#section-1.2 图片来源: https : //tools.ietf.org/html/rfc6749#section-1.2

OAuth 2.0 protocol can be divided into three main steps:

OAuth 2.0协议可分为三个主要步骤:

  1. [steps A-C] Receive an authorization_code (hereinafter, code).

    [步骤AC]接收authorization_code (以下称为code )。

  2. [steps D-E] Exchange code to access_token.

    [步骤DE]将code交换到access_token

  3. Get resource via access_token.

    通过access_token获取资源。

Let’s elaborate on the process of getting code value:

让我们详细说明获得code值的过程:

  1. [Step A] Client redirects the user to the service provider.

    [步骤A]客户端将用户重定向到服务提供商。

  2. [Step B] Service provider requests permission from the user to provide the client with the data (arrow B up). The user provides data access (arrow B to the right).

    [步骤B]服务提供商向用户请求许可,以向客户端提供数据(箭头B向上)。 用户提供数据访问权限(右侧箭头B)。

  3. [Step C] Service provider returns code to the user browser which redirects code to the client.

    [步骤C]服务提供商将code返回到用户浏览器,后者将code重定向到客户端。

Let’s talk more the process of getting access_token:

让我们更多地讨论获取access_token的过程:

  1. [Step D] Client server sends a request for access_token. Code, client_secret and redirect_uri are included in the request.

    [步骤D]客户端服务器发送一个access_token请求。 Codeclient_secretredirect_uri包含在请求中。

  2. [Step E] In case of valid code, client_secret and redirect_uri, access_token is provided.

    [步骤E]在有效code client_secretredirect_uri情况下,提供access_token

Request for access_token is done according to the server-to-server scheme: therefore, in general, attacker have to hack the client service server or service provider server in order to steal access_token.

access_token请求是根据服务器到服务器的方案完成的:因此,通常,攻击者必须破解客户端服务服务器或服务提供者服务器才能窃取access_token

Now let’s look at mobile OAuth 2.0 scheme without backend (client-to-server interaction).

现在,让我们看一下没有后端(客户端到服务器的交互)的移动OAuth 2.0方案。

Picture origin: https://tools.ietf.org/html/rfc8252#section-4.1 图片来源: https : //tools.ietf.org/html/rfc8252#section-4.1

The main scheme is divided into the same main steps:

主要方案分为相同的主要步骤:

  1. [steps 1-4 in the picture] Get code.

    [图片中的步骤1-4]获取code

  2. [steps 5-6 in the picture] Exchange code to access_token

    [图片中的步骤5-6]交换codeaccess_token

  3. Gain resource access via access_token

    通过access_token获得资源访问

However, in this case mobile app has also the server functions; therefore, client_secret would be embedded into the application. As a result, client_secret cannot be kept hidden from attacker on mobile devices. Embedded client_secret can be extracted in two ways: by analyze the application-to-server traffic or by reverse engineering. Both can be easily realized, and that’s why client_secret is useless on mobile devices.

但是,在这种情况下,移动应用程序还具有服务器功能。 因此, client_secret将被嵌入到应用程序中。 结果, client_secret无法在移动设备上对攻击者隐藏。 嵌入式client_secret可以通过两种方式提取:通过分析应用程序到服务器的流量或通过反向工程。 两者都可以轻松实现,这就是为什么client_secret在移动设备上无用的原因。

You might ask: «Why don’t we get access_token right away?» You might think that this extra step is unnecessary. Furthermore there’s Implicit Grant scheme that allows a client to receive access_token right away. Even though, it can be used in some cases, Implicit Grant wouldn’t work for secure mobile OAuth 2.0.

您可能会问:«为什么我们不立即获得access_token ?» 您可能会认为多余的步骤是不必要的。 此外,还有一个隐式授予方案,该方案允许客户端立即接收access_token 。 即使可以在某些情况下使用它, 隐式授予也不适用于安全的移动OAuth 2.0。

在移动设备上重定向 (Redirection on mobile devices)

In general, Custom URI Scheme and AppLink mechanisms are used for browser-to-app redirect. Neither of these mechanisms can be as secure as browser redirects on its own.

通常, 自定义URI方案AppLink机制用于浏览器到应用程序的重定向。 这两种机制都无法像浏览器自行重定向一样安全。

Custom URI Scheme (or deep link) is used in the following way: a developer determines an application scheme before deployment. The scheme can be any, and one device can have several applications with the same scheme. 自定义URI方案 (或深层链接)以以下方式使用:开发人员在部署之前确定应用程序方案。 该方案可以是任何方案,并且一个设备可以具有相同方案的多个应用程序。

It makes things easier when every scheme on a device corresponds with one application. But what if two applications register the same scheme on one device? How does the operation system decide which app to open when contacted via Custom URI Scheme? Android will show a window with a choice of an app and a link to follow. iOS doesn’t have a procedure for this and, therefore, either application may be opened. Anyways, attacker gets a chance to intercept code or access_token.

当设备上的每个方案都与一个应用程序相对应时,这使事情变得更容易。 但是,如果两个应用程序在一台设备上注册相同的方案怎么办? 通过自定义URI方案联系时,操作系统如何决定打开哪个应用程序? Android将显示一个窗口,其中包含一个应用程序的选择以及一个链接。 iOS 没有为此提供程序 ,因此,任何一个应用程序都可以打开。 无论如何,攻击者就有机会拦截代码或access_token

Unlike Custom URI Scheme, AppLink guarantees to open the right application, but this mechanism has several flaws:

与自定义URI方案不同, AppLink保证打开正确的应用程序,但是此机制有几个缺陷:

  1. Every service client must undergo the verification procedure.

    每个服务客户都必须经过验证程序

  2. Android users can turn AppLink off for a specific app in settings.

    Android用户可以在设置中为特定应用程序关闭AppLink。

  3. Android versions older than 6.0 and iOS versions older than 9.0 don’t support AppLink.

    早于6.0的Android版本和早于9.0的iOS版本不支持AppLink。

All these AppLink flaws increase the learning curve for potential service clients and may result in user OAuth 2.0 failure under some circumstances. That’s why many developers don’t choose AppLink mechanism as substitution for browser redirect in OAuth 2.0 protocol.

所有这些AppLink缺陷都会增加潜在服务客户端的学习难度,并且在某些情况下可能导致用户OAuth 2.0失败。 这就是为什么许多开发人员不选择AppLink机制来替代OAuth 2.0协议中的浏览器重定向的原因。

好,有什么要攻击的? (OK, what is there to attack?)

Mobile OAuth 2.0 problems have created some specific attacks. Let’s see what they are and how they work.

移动OAuth 2.0问题导致了一些特定的攻击。 让我们看看它们是什么以及它们如何工作。

授权码拦截攻击 (Authorization Code Interception Attack)

Let’s consider the situation where user device has a legitimate application (OAuth 2.0 client) and a malicious application which registered the same scheme as the legitimate one. The picture below shows the attack scheme.

让我们考虑用户设备具有合法应用程序(OAuth 2.0客户端)和恶意应用程序注册了与合法应用程序相同的方案的情况。 下图显示了攻击方案。

https://tools.ietf.org/html/rfc7636#section-1https://tools.ietf.org/html/rfc7636#section-1

Here’s the problem: at the fourth step, the browser returns the code in the application via Custom URI Scheme and, therefore, the code can be intercepted by a malicious app (since it’s registered the same scheme as a legitimate app). Then the malicious app changes code to access_token and receives access to the user’s data.

这就是问题所在:第四步,浏览器通过“自定义URI方案”返回应用程序中的code ,因此,该code可能会被恶意应用程序拦截(因为它注册的程序与合法应用程序相同)。 然后,恶意应用将code更改为access_token并接收对用户数据的访问。

What’s the protection? In some cases, you can use inter-process communication; we'll talk about it later. In general, you need a scheme called Proof Key for Code Exchange. It’s described in the scheme below.

有什么保护? 在某些情况下,您可以使用进程间通信。 我们稍后再讨论。 通常,您需要一个称为代码交换证明密钥的方案。 在下面的方案中进行了描述。

Picture origin: https://tools.ietf.org/html/rfc7636#section-1.1 图片来源: https : //tools.ietf.org/html/rfc7636#section-1.1

Client request has several extra parameters: code_verifier, code_challenge (in the scheme t(code_verifier)) and code_challenge_method (in the scheme t_m).

客户请求有几个额外的参数: code_verifiercode_challenge (在方案t(code_verifier) )和code_challenge_method (在方案t_m )。

Code_verifier — is a random number Code_verifier —是一个随机数 with a minimum length of 256 bit, ,最小长度为256位that is used only once. So, a client must generate a new 只能使用一次 。 因此,客户端必须为每个 code_verifier for every code请求生成一个新的 code request. code_verifierCode_challenge_method — this is a name of a conversion function, mostly SHA-256. Code_challenge_method —这是转换函数的名称,主要是SHA-256。 Code_challenge — is Code_challenge -是 code_verifier to which code_verifiercode_challenge_method conversion was applied to and which coded in URL Safe Base64. code_challenge_method转化应用和网址安全base64编码哪。

Conversion of code_verifier into code_challenge is necessary to rebuff the attack vectors based on code_verifier interception (for example, from the device system logs) when requesting code.

请求code时,必须根据code_verifier拦截(例如,从设备系统日志中获取)来拒绝攻击向量,必须将code_challenge转换为code_verifier

In case when a user device

如果用户设备

不支持 (doesn’t support)

SHA-256, a

SHA-256,一个

client is allowed to use plain conversion of code_verifierclient is allowed to use plain conversion of code_verifier

This is how this scheme works:

此方案的工作方式如下:

  1. Client generates code_verifier and memorizes it.

    客户端生成code_verifier并将其存储。

  2. Client chooses code_challenge_method and receives code_challenge from code_verifier.

    客户选择code_challenge_method和接收code_challengecode_verifier

  3. [Step А] Client requests code, with code_challenge and code_challenge_method added to the request.

    [步骤А]客户请求code ,其中code_challengecode_challenge_method添加到请求中。

  4. [Step B] Provider stores code_challenge and code_challenge_method on the server and returns code to a client.

    [步骤B]提供程序将code_challengecode_challenge_method存储在服务器上,并将code返回给客户端。

  5. [Step C] Client requests access_token, with code_verifier added to it.

    [步骤C]客户端请求access_token ,并添加了code_verifier

  6. Provider receives code_challenge from incoming code_verifier, and then compares it to code_challenge, that it saved.

    提供商接收code_challenge从传入code_verifier ,然后将其进行比较,以code_challenge ,它保存。

  7. [Step D] If the values match, the provider gives client access_token.

    [步骤D]如果值匹配,则提供程序将给客户端access_token

To understand why code_challenge prevents code interception let’s see how the protocol flow looks from attacker’s perspective.

要了解为什么code_challenge阻止代码拦截,让我们从攻击者的角度看协议流的外观。

  1. First, legitimate app requests code (code_challenge and code_challenge_method are sent together with the

    首先,合法的应用程序请求code ( code_challengecode_challenge_method

    请求 (request)

    ).

    )。

  2. Malicious app intercepts code (but not code_challenge, since code_challenge is not in the response).

    恶意应用会拦截code (但不会拦截code_challenge ,因为代码_challenge不在响应中)。

  3. Malicious app requests access_token (with valid code, but

    恶意应用程序请求access_token (使用有效code ,但

    没有 (without)

    valid

    有效

    code_verifier).code_verifier )。
  4. The server notices mismatch of code_challenge and raises an error message.

    服务器注意到code_challenge不匹配,并引发错误消息。

Note that the attacker can’t guess code_verifier (random 256 bit value!) or find it somewhere in the logs (since first request actually transmitted code_challenge).

请注意,攻击者无法猜测code_verifier (随机256位值!)或在日志中的某个位置找到它(因为第一个请求实际上发送了code_challenge )。

So, code_challenge answers the question of the service provider: «Is access_token requested by the same app client that requested code or a different one?».

因此, code_challenge回答了服务提供商的问题:“ access_token是由请求code的同一应用程序客户端请求的,还是由不同的请求?

OAuth 2.0 CSRF (OAuth 2.0 CSRF)

OAuth 2.0 CSRF is relatively harmless when OAuth 2.0 is used for authorization. It’s a completely different story when OAuth 2.0 is used for authentication. In this case OAuth 2.0 CSRF often leads to account takeover.

使用OAuth 2.0进行授权时,OAuth 2.0 CSRF相对无害。 当使用OAuth 2.0进行身份验证时,情况就完全不同了。 在这种情况下,OAuth 2.0 CSRF通常会导致帐户接管。

Let’s talk more about the CSRF attack conformably to OAuth 2.0 through the example of taxi app client and provider.com provider. First, an attacker on his own device logs into attacker@provider.com account and receives code for taxi. Then he interrupts OAuth 2.0 process and generates a link:

让我们通过的士应用程序客户端和provider.com提供程序示例,进一步讨论符合OAuth 2.0的CSRF攻击。 首先,攻击者使用自己的设备登录到attacker@provider.com帐户,并接收出租车code 。 然后,他中断OAuth 2.0进程并生成一个链接:

com.taxi.app://oauth?
code=b57b236c9bcd2a61fcd627b69ae2d7a6eb5bc13f2dc25311348ee08df43bc0c4

Then the attacker sends this link to his victim, for example, in the form of a mail or text message from taxi stuff. The victim clicks the link, taxi app opens and receives access_token. As a result, they find themselves in the

然后,攻击者将此链接发送给受害者,例如以出租车物品的邮件或文本消息的形式。 受害者单击链接,出租车应用程序打开并接收access_token 。 结果,他们发现自己处于

攻击者 (attacker’s)

taxi account. Unaware of that, the victim uses this account: make trips, enters personal data, etc.

计程车帐户。 受害人不知道这一点,而是使用此帐户:出差,输入个人数据等。

Now the attacker can log into the victim’s taxi account any time, as it’s linked to attacker@provider.com. CSRF login attack allowed the violator to steal an account.

现在,攻击者可以随时登录到受害者的出租车帐户,因为它已链接到attacker@provider.com 。 CSRF登录攻击允许违规者窃取帐户。

CSRF attacks are usually rebuffed with a CSRF token (it’s also called state), and OAuth 2.0 is no exception. How to use the CSRF token:

通常使用CSRF令牌(也称为state )来拒绝CSRF攻击,OAuth 2.0也不例外。 如何使用CSRF令牌:

  1. Client application generates and saves CSRF token on a client’s mobile device.

    客户端应用程序会生成CSRF令牌并将其保存在客户端的移动设备上。

  2. Client application includes the CSRF token in code access request.

    客户端应用程序将CSRF令牌包含在code访问请求中。

  3. Server returns the same CSRF token with code in its response.

    服务器在响应中返回带有code的相同CSRF令牌。

  4. Client application compares the incoming and saved CSRF tokens. If their values match, the process goes on.

    客户端应用程序比较传入和保存的CSRF令牌。 如果它们的值匹配,则过程继续。

CSRF token requirements: nonce must be at least 256 bit and received from a good source of pseudo-random sequences.

CSRF令牌要求: 随机数必须至少为256位,并且必须从良好的伪随机序列源中接收。

In a nutshell, CSRF token allows an application client to answer the following question: «Was that me who initiated access_token request or someone is trying to trick me?».

简而言之,CSRF令牌允许应用程序客户端回答以下问题:“是发起access_token请求的我还是有人试图欺骗我?”。

硬编码的客户机密 (Hardcoded client secret)

Mobile applications without a backend sometimes store hardcoded client_id and client_secret values. Of course they can be easily extracted by reverse engineering app.

没有后端的移动应用程序有时会存储硬编码的client_idclient_secret值。 当然,可以通过逆向工程应用轻松提取它们。

Impact of exposing client_id and client_secret highly depends on how much trust service provider puts on the certain client_id, client_secret pair. One uses them just to distinguish one client from another while others open hidden API endpoints or make a softer rate limits for some clients.

公开client_idclient_secret很大程度上取决于信任服务提供者对特定的client_idclient_secret对的信任程度。 一个使用它们只是为了区分一个客户端与另一个客户端,而其他客户端则打开隐藏的API端点或对某些客户端设置较慢的速率限制。

The article Why OAuth API Keys and Secrets Aren't Safe in Mobile Apps elaborates more on this topic.

为什么移动应用程序中的OAuth API密钥和机密不安全一文详细介绍了此主题。

恶意应用程式充当合法客户 (Malicious app acting as a legitimate client)

Some malicious apps can imitate the legitimate apps and display a consent screen on their behalf (a consent screen is a screen where a user sees: «I agree to provide access to…»). User might click «allow» and provide the malicious app with his data.

一些恶意应用程序可以模仿合法应用程序并代表它们显示同意屏幕(同意屏幕是用户看到的屏幕:“我同意提供对…的访问权限”)。 用户可以单击“允许”,然后向恶意应用程序提供其数据。

Android and iOS provide the mechanisms of applications cross-check. An application provider can make sure that a client application is legitimate and vice versa.

Android和iOS提供了应用程序交叉检查的机制。 应用程序提供商可以确保客户端应用程序是合法的,反之亦然。

Unfortunately, if OAuth 2.0 mechanism uses a thread via browser, it’s impossible to defend against this attack.

不幸的是,如果OAuth 2.0机制通过浏览器使用线程,则无法防御这种攻击。

其他攻击 (Other attacks)

We took a closer look at the attacks exclusive to mobile OAuth 2.0. However, let’s not forget about the original OAuth 2.0: redirect_uri substitution, traffic interception via unsecure connection, etc. You can read more about it here.

我们仔细研究了移动OAuth 2.0专有的攻击。 但是,我们不要忘记原始的OAuth 2.0: redirect_uri替换,通过不安全连接进行的流量拦截等。您可以在此处了解更多信息。

如何安全地做? (How to do it securely?)

We’ve learned how OAuth 2.0 protocol works and what vulnerabilities it has on mobile devices. Now let’s put the separate pieces together to have a secure mobile OAuth 2.0 scheme.

我们已经了解了OAuth 2.0协议的工作原理以及它在移动设备上的漏洞。 现在,让我们将各个部分放在一起,以形成一个安全的移动OAuth 2.0方案。

OAuth 2.0的好坏 (Good, bad OAuth 2.0)

Let’s start with the right way to use consent screen. Mobile devices have two ways of opening a web page in a mobile application.

让我们从正确的方式使用同意屏幕开始。 移动设备有两种在移动应用程序中打开网页的方式。

The first way is via Browser Custom Tab (on the left in the picture).

第一种方法是通过“浏览器自定义”选项卡(在图片的左侧)。

注意 (Note)

: Browser Custom Tab for Android is called Chrome Custom Tab, and for iOS – SafariViewController. It’s just a browser tab displayed in the app: there’s no visual switching between the applications.

:适用于Android的浏览器自定义选项卡称为Chrome自定义选项卡,适用于iOS的称为SafariViewController。 这只是应用程序中显示的浏览器选项卡:在应用程序之间没有视觉切换。

The second way is via WebView (on the right in the picture) and I consider it bad in respect to the mobile OAuth 2.0.

第二种方法是通过WebView(在图片的右侧),对于移动OAuth 2.0而言,我认为它很糟糕。

WebView is a embedded browser for a mobile app.

WebView是用于移动应用程序的嵌入式浏览器。

"Embedded browser" means that access to cookies, storage, cache, history, and other Safari and Chrome data is forbidden for WebView. The reverse is also correct: Safari and Chrome cannot get access to WebView data.

嵌入式浏览器 ”表示WebView禁止访问Cookie,存储,缓存,历史记录以及其他Safari和Chrome数据。 反之亦然:Safari和Chrome无法访问WebView数据。

"Mobile app browser" means that a mobile app that runs WebView has

移动应用浏览器 ”表示运行WebView的移动应用具有

充分 (full)

access to cookies, storage, cache, history and other WebView data.

访问cookie,存储,缓存,历史记录和其他WebView数据。

Now, imagine: a user clicks «enter with…» and a WebView of a malicious app requests his login and password from the service provider.

现在,想象一下:用户单击“输入...”,并且恶意应用程序的WebView向服务提供商请求其登录名和密码。

Epic fail:

史诗失败:

  1. The user enters his login and password for the service provider account in the app, that can easily steal this data.

    用户在应用程序中输入其服务提供商帐户的登录名和密码,可以轻松窃取此数据。

  2. OAuth 2.0 was initially developed to not to enter the service provider login and password.

    OAuth 2.0最初是为了不输入服务提供商的登录名和密码而开发的。

    The user gets used to entering his login and password anywhere thus increasing a

    用户习惯于在任何地方输入其登录名和密码,从而增加了

    fishing possibility.

    钓鱼的可能性。

Considering all the cons of WebView, an obvious conclusion offers itself: use Browser Custom Tab for consent screen.

考虑到WebView的所有弊端,一个显而易见的结论是:使用“浏览器自定义选项卡”作为同意屏幕。

If anyone has arguments in favor of WebView instead of Browser Custom Tab, I’d appreciate if you write about it in the comments.

如果有人赞成使用WebView而不是“浏览器自定义选项卡”,那么如果您在注释中写到它,将不胜感激。

安全的移动OAuth 2.0方案 (Secure mobile OAuth 2.0 scheme)

We’re going to use Authorization Code Grant scheme, since it allows us to add code_challenge as well as state and defend against a code interception attack and OAuth 2.0 CSRF.

我们将使用授权代码授予方案,因为它允许我们添加code_challenge以及state和防御代码拦截攻击和OAuth 2.0 CSRF。

Picture origin: https://tools.ietf.org/html/rfc8252#section-4.1 图片来源: https : //tools.ietf.org/html/rfc8252#section-4.1

Code access request (steps 1-2) will look as follows:

代码访问请求(步骤1-2)如下所示:

https://o2.mail.ru/code?
redirect_uri=com.mail.cloud.app%3A%2F%2Foauth&
state=927489cb2fcdb32e302713f6a720397868b71dd2128c734181983f367d622c24& code_challenge=ZjYxNzQ4ZjI4YjdkNWRmZjg4MWQ1N2FkZjQzNGVkODE1YTRhNjViNjJjMGY5MGJjNzdiOGEzMDU2ZjE3NGFiYw%3D%3D&
code_challenge_method=S256&
scope=email%2Cid&
response_type=code&
client_id=984a644ec3b56d32b0404777e1eb73390c

At step 3, the browser gets a response with redirect:

在第3步中,浏览器将获得带有重定向的响应:

com.mail.cloud.app://oаuth?
code=b57b236c9bcd2a61fcd627b69ae2d7a6eb5bc13f2dc25311348ee08df43bc0c4&
state=927489cb2fcdb32e302713f6a720397868b71dd2128c734181983f367d622c24

At step 4, the browser opens Custom URI Scheme and pass CSRF token over to a client app.

在步骤4,浏览器打开“自定义URI方案”,并将CSRF令牌传递给客户端应用。

access_token request (step 5): access_token请求(步骤5):
https://o2.mail.ru/token?
code_verifier=e61748f28b7d5daf881d571df434ed815a4a65b62c0f90bc77b8a3056f174abc&
code=b57b236c9bcd2a61fcd627b69ae2d7a6eb5bc13f2dc25311348ee08df43bc0c4&
client_id=984a644ec3b56d32b0404777e1eb73390c

The last step brings a response with access_token.

最后一步带来了带有access_token的响应。

This scheme is generally secure, but there are some special cases when OAuth 2.0 can be simpler and more secure.

这种方案通常是安全的,但是在某些特殊情况下OAuth 2.0可以更简单,更安全。

Android IPC (Android IPC)

Android has a mechanism of bidirectional data communication between processes: IPC (inter-process communication). IPC is better than Custom URI Scheme for two reasons:

Android具有进程之间的双向数据通信机制:IPC(进程间通信)。 IPC优于自定义URI方案有两个原因:

  1. An app that opens IPC channel can confirm authenticity of an app it’s opening by its certificate. The reverse is also true: the opened app can confirm authenticity of the app that opened it.

    打开IPC频道的应用程序可以通过其证书确认其打开的应用程序的真实性。 反之亦然:打开的应用程序可以确认打开它的应用程序的真实性。

  2. If a sender sends a request via IPC channel, it can receive an answer via the same channel. Together with the cross-check (item 1), it means that no foreign process can intercept access_token.

    如果发送方通过IPC通道发送请求,则可以通过同一通道接收答复。 与交叉检查(项目1)一起,这意味着没有外部进程可以拦截access_token

Therefore, we can use Implicit Grant to simplify mobile OAuth 2.0 scheme. No code_challenge and state also means less attack surface. We can also lower the risks of malicious apps acting like legitimate client trying to steal the user accounts.

因此,我们可以使用隐式授予来简化移动OAuth 2.0方案。 没有code_challengestate也意味着更少的攻击面。 我们还可以降低恶意应用程序像合法客户端那样试图窃取用户帐户的风险。

客户专用SDK (SDK for clients)

Besides implementing this secure mobile OAuth 2.0 scheme, a provider should develop SDK for his clients. It’ll simplify OAuth 2.0 implementation on a client side and simultaneously reduce the number of errors and vulnerabilities.

除了实施此安全的移动OAuth 2.0方案外,提供商还应为其客户开发SDK。 它将简化客户端的OAuth 2.0实施,同时减少错误和漏洞的数量。

结论 (Conclusions)

Let me summarise it for you. Here is the (basic) checklist for secure OAuth 2.0 for OAuth 2.0 providers:

让我为您总结一下。 这是OAuth 2.0提供程序的安全OAuth 2.0的(基本) 清单

  1. Strong foundation is crucial. In case of mobile OAuth 2.0, the foundation is a scheme or a protocol picked out for implementation. It’s easy to make mistakes whilst implementing your own OAuth 2.0 scheme. Others have already taken knocks and learned their lesson; there’s nothing wrong with learning from their mistakes and make secure implementation in one go. The most secure mobile OAuth 2.0 scheme is described in How to do it securely?

    坚实的基础至关重要。 在移动OAuth 2.0的情况下,基础是为实施选择的方案或协议。 在实施自己的OAuth 2.0方案时很容易出错。 其他人已经敲门并吸取了教训。 从他们的错误中学习并一劳永逸地进行安全实施并没有错。 如何安全地进行操作中介绍了最安全的移动OAuth 2.0方案。

  2. Access_token and other sensitive data must be stored in Keychain for iOS and in Internal Storage for Android. These storages were specifically developed just for that. Content Provider can be used in Android, but it must be securely configured.

    Access_token和其他敏感数据必须存储在iOS的钥匙串中和Android的内部存储中。 这些存储是专门为此而开发的。 Content Provider可以在Android中使用,但必须进行安全配置。

  3. Client_secret is

    Client_secret

    无用 (useless)

    , unless it’s stored in backend. Do not give it away to the public clients.

    ,除非存储在后端。 不要将其赠送给公共客户。

  4. Do not use WebView for consent screen; use Browser Custom Tab.

    不要将WebView用于同意屏幕; 使用浏览器自定义标签。

  5. To defend against code interception attack, use code_challenge.

    要防御代码拦截攻击,请使用code_challenge

  6. To defend against OAuth 2.0 CSRF, use state.

    要防御OAuth 2.0 CSRF,请使用state

  7. Use HTTPS

    使用HTTPS

    到处 (everywhere)

    , with downgrade forbidden to HTTP. Here is

    ,禁止降级为HTTP。 这是

    3-minute demo explaining why (with example from a bug bounty).3分钟的演示,解释原因(并附有漏洞赏金示例)。
  8. Follow the cryptography

    遵循密码学

    标准 (standards)

    (choice of algorithm, length of tokens, etc). You may copy the data and figure out why it’s done this way, but do not roll your own crypto.

    (算法选择,令牌长度等)。 您可以复制数据并弄清楚为什么要这样做,但不要自行加密。

  9. Code must be used only once, with a short lifespan.

    Code只能使用一次,并且使用寿命很短。

  10. From an app client side, check what you open for OAuth 2,0; and from an app provider side, check who opens you for OAuth 2.0.

    在应用客户端,检查您为OAuth 2,0打开的内容; 然后从应用程序提供商的角度,检查谁为您打开了OAuth 2.0。

  11. Keep in mind common OAuth 2.0 vulnerabilities. Mobile OAuth 2.0 enlarges and completes the original one, therefore, redirect_uri check for an exact match and other recommendations for the original OAuth 2,0 are still in force.

    请记住常见的OAuth 2.0漏洞 。 移动OAuth 2.0会放大并完成原始OAuth 2.0,因此, redirect_uri检查是否完全匹配,并且其他针对原始OAuth 2,0的建议仍然有效。

  12. You should provide your clients with SDK. They’ll have fewer bugs and vulnerabilities and it’ll be easier for them to implement your OAuth 2.0.

    您应该为客户提供SDK。 他们的错误和漏洞更少,并且他们可以更轻松地实现您的OAuth 2.0。

进一步阅读 (Further reading)

  1. «Vulnerabilities of mobile OAuth 2.0» https://www.youtube.com/watch?v=vjCF_O6aZIg

    «移动OAuth 2.0的漏洞» https://www.youtube.com/watch?v=vjCF_O6aZIg

  2. OAuth 2.0 race condition research https://hackerone.com/reports/55140

    OAuth 2.0竞争状况研究https://hackerone.com/reports/55140

  3. Almost everything about OAuth 2.0 in one place https://oauth.net/2/

    关于OAuth 2.0的几乎所有内容都集中在一个地方https://oauth.net/2/

  4. Why OAuth API Keys and Secrets Aren't Safe in Mobile Apps https://developer.okta.com/blog/2019/01/22/oauth-api-keys-arent-safe-in-mobile-apps

    为什么OAuth API密钥和秘密在移动应用程序中不安全https://developer.okta.com/blog/2019/01/22/oauth-api-keys-arent-safe-in-mobile-apps

  5. [RFC] OAuth 2.0 for Native Apps https://tools.ietf.org/html/rfc8252

    [RFC]适用于本机应用程序的OAuth 2.0 https://tools.ietf.org/html/rfc8252

  6. [RFC] Proof Key for Code Exchange by OAuth Public Clients https://tools.ietf.org/html/rfc7636

    [RFC] OAuth公共客户端用于代码交换的证明密钥https://tools.ietf.org/html/rfc7636

  7. [RFC] OAuth 2.0 Threat Model and Security Considerations https://tools.ietf.org/html/rfc6819

    [RFC] OAuth 2.0威胁模型和安全注意事项https://tools.ietf.org/html/rfc6819

  8. [RFC] OAuth 2.0 Dynamic Client Registration Protocol https://tools.ietf.org/html/rfc7591

    [RFC] OAuth 2.0动态客户端注册协议https://tools.ietf.org/html/rfc7591

  9. Google OAuth 2.0 for Mobile & Desktop Apps https://developers.google.com/identity/protocols/OAuth2InstalledApp

    适用于移动和桌面应用程序的Google OAuth 2.0 https://developers.google.com/identity/protocols/OAuth2InstalledApp

学分 (Credits)

Thanks to all who helped me to write this article. Especially to Sergei Belov, Andrei Sumin, Andrey Labunets for the feedback about technical details, to Pavel Kruglov for the English translation and to Daria Yakovleva for the help with release of Russian version of this article.

感谢所有帮助我写这篇文章的人。 特别是对于谢尔盖·贝洛夫(Sergei Belov),安德烈·苏敏(Andrei Sumin),安德烈·拉布涅(Andrey Labunets)提供有关技术细节的反馈,尤其是帕维尔·克鲁格洛夫(Pavel Kruglov)的英文翻译,以及达里亚·雅科夫列娃(Daria Yakovleva)的帮助,以发行本文的俄语版本。

翻译自: https://habr.com/en/company/mailru/blog/456702/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值