令牌提交的身份验证失败_您确定您没有将用户的身份验证令牌泄漏给第三方吗?

令牌提交的身份验证失败

Are you an Android developer who is inclined towards security or an application security guy who’s keen to connect multiple dots to identify a cool security bug? Were you oblivious that OkHttp, the Friend of Android developers retains auth headers during redirection? If yes, then this story would be interesting for you. It talks about the behaviour of OkHttp to retain auth headers during redirection to third-party domains.

您是倾向于安全性的Android开发人员,还是热衷于连接多个点以识别很酷的安全性错误的应用程序安全性专家? 您是否忘记了Android开发者之友OkHttp在重定向期间保留auth标头? 如果 ,那么这个故事对您来说很有趣。 它讨论了OkHttp在重定向到第三方域期间保留身份验证标头的行为。

To better understand this, let us first brush up some fundamental things around the issue. If you are already aware of OkHttp and concept of application and network Interceptors, you may skip the following sections and directly start from The Problem!

为了更好地理解这一点,让我们首先回顾一下有关此问题的一些基本知识。 如果您已经了解OkHttp以及应用程序和网络拦截器的概念,则可以跳过以下部分,直接从问题开始

什么是OkHttp? (What is OkHttp?)

OkHttp is an HTTP client, it is a third-party library developed by Square for sending and receiving HTTP-based network requests. It is also the underlying library for Retrofit which is another HTTP client used widely these days.

OkHttp是一个HTTP客户端,它是Square开发的用于发送和接收基于HTTP的网络请求的第三方库。 它也是Retrofit的基础库,这是当今广泛使用的另一个HTTP客户端。

OkHttp拦截器 (OkHttp Interceptors)

Interceptors are a powerful mechanism that can monitor, rewrite, and retry network calls. For large-scale applications where we have numerous APIs communicating with our backend, it can be tedious and super-repetitive to write common logics such as encrypting the request body, decrypting the response body, attaching access tokens to request, handling specific responses(e.g. HTTP-401-Unauthorized/HTTP-403-Forbidden), etc. for each and every API call and this is where Interceptors helps us to rescue.

拦截器是一种强大的机制,可以监视,重写和重试网络调用。 对于我们有大量与后端通信的API的大型应用程序,编写通用逻辑(例如加密请求正文,解密响应正文,将访问令牌附加到请求,处理特定响应(例如, HTTP-401-Unauthorized / HTTP-403-Forbidden)等等,Interceptor可以帮助我们进行救援。

The way we have API Gateway at the backend which acts as an entry point from the backend side, we can consider Interceptors to be the gateway for all the request that our frontend makes.

在后端使用API​​网关作为后端的入口点的方式,我们可以将Interceptor视为前端提出的所有请求的网关

申请与 网络拦截器 (Application Vs. Network Interceptors)

The OkHttp Interceptors can be registered as either Application or Network interceptors as shown below:

所述OkHttp拦截器可以注册为是A pplication或N etwork 拦截器如下图所示:

Image for post
Square 正方形

应用拦截器 (Application Interceptor)

client = new OkHttpClient.Builder()
.addInterceptor(new SessionTokenInterceptor())

Network Interceptor

网络拦截器

client = new OkHttpClient.Builder()
.addNetworkInterceptor(new LoggingInterceptor())

When we attach an Interceptor as a Network interceptor the interception logic is applied at the intermediate request and response as well, for example, redirects and retries. Whereas, in the case of Application interceptors the logic is only applied to the first request and the last response in the case of redirects.

当我们将拦截器附加为网络拦截器时,拦截逻辑也会应用于中间请求和响应,例如重定向和重试。 而在应用程序拦截器的情况下,逻辑仅在重定向的情况下应用于第一个请求和最后一个响应。

Let us understand it through the example quoted in the official docs wherein we have written a LoggingInterceptor which logs the request and responses and we make a network call to the URL http://www.publicobject.com/helloworld.txtwhich redirects to https://publicobject.com/helloworld.txtby returning a HTTP-3XX response.

让我们通过官方文档中引用的示例来理解它,其中我们编写了一个LoggingInterceptor来记录请求和响应,并通过网络调用URL http://www.publicobject.com/helloworld.txt 重定向到https://publicobject.com/helloworld.txt通过返回HTTP-3XX响应来https://publicobject.com/helloworld.txt

In the case the LoggingInterceptor is attached as an application interceptor we get the following in the Logs:

如果将LoggingInterceptor附加为应用程序拦截器,我们将在Logs中获得以下内容:

INFO: Sending request http://www.publicobject.com/helloworld.txt on null
User-Agent: OkHttp Example
INFO: Received response for https://publicobject.com/helloworld.txt in 1179.7ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/plain
Content-Length: 1759
Connection: keep-alive

And when it is attached as a network interceptor the following is pushed to the logs:

当它作为网络拦截器连接时,以下内容将被推送到日志中:

INFO: Sending request http://www.publicobject.com/helloworld.txt on Connection{www.publicobject.com:80, proxy=DIRECT hostAddress=54.187.32.157 cipherSuite=none protocol=http/1.1}
User-Agent: OkHttp Example
Host: www.publicobject.com
Connection: Keep-Alive
Accept-Encoding: gzip
INFO: Received response for http://www.publicobject.com/helloworld.txt in 115.6ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/html
Content-Length: 193
Connection: keep-alive
Location: https://publicobject.com/helloworld.txt
INFO: Sending request https://publicobject.com/helloworld.txt on Connection{publicobject.com:443, proxy=DIRECT hostAddress=54.187.32.157 cipherSuite=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA protocol=http/1.1}
User-Agent: OkHttp Example
Host: publicobject.com
Connection: Keep-Alive
Accept-Encoding: gzip
INFO: Received response for https://publicobject.com/helloworld.txt in 80.9ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/plain
Content-Length: 1759
Connection: keep-alive

I think you should be having enough understanding of the fundamentals to properly understand and identify the security issue.

我认为您应该对基础知识有足够的了解,以正确理解和识别安全问题。

问题! (The Problem!)

The security issue arises when we use an Interceptor for attaching the access token to the HTTP request and this Interceptor is added to the OkHttp client as an application interceptor.

当我们使用拦截器将访问令牌附加到HTTP请求并将此拦截器作为应用程序拦截器添加到OkHttp客户端时,就会出现安全问题。

The application is safe if any of this stands true:

如果满足以下任一条件,则该应用程序是安全的:

  • You are not using Interceptors for adding access tokens

    您没有使用拦截器来添加访问令牌
  • You pass access tokens to backend using an HTTP header named Authorization

    您使用名为Authorization的HTTP标头将访问令牌传递给后端

  • You are using Interceptors but your backend never redirects the users to any third-party domains

    您正在使用拦截器,但后端从未将用户重定向到任何第三方域

Since OkHttp Application Interceptors automatically attaches the headers to the redirects even if the redirection is to external domains if the access token is passed using any name except Authorization. I tested this behaviour on OkHttp v3.5

因为OkHttp应用程序拦截器会自动将标头附加到重定向,即使重定向使用外部域(即使使用Authorization以外的任何名称传递访问令牌)也是如此。 我在OkHttp v3.5上测试了此行为

演示时间 (Demo Time)

Image for post

For the demo purposes, I have created a sample Android application that makes an API call using OkHttp to backend and gets a redirection response. You can find the source code here.

出于演示目的,我创建了一个示例Android应用程序,该应用程序使用OkHttp进行后端API调用并获取重定向响应。 您可以在此处找到源代码。

I have also used two interceptors viz. SessionTokenInterceptor and LoggingInterceptor. The former one is used to attach the session token to the HTTP request and the latter one is used to log all the requests and response in order to determine unintended third-party data leakage. The following are the code snippets from the application’s code

我还使用了两个拦截器,即。 SessionTokenInterceptorLoggingInterceptor 。 前者用于将会话令牌附加到HTTP请求,而后者用于记录所有请求和响应,以确定意外的第三方数据泄漏。 以下是应用程序代码中的代码段

SessionTokenInterceptor

SessionTokenInterceptor

public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Request newRequest=request.newBuilder().addHeader("Auth", sessionToken)
.build();
return chain.proceed(newRequest);
}

LoggingInterceptor

测井拦截器

@Override public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
Log.i("Logging Interceptor",String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
Response response = chain.proceed(request);
long t2 = System.nanoTime();
Log.i("Logging Interceptor",String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
return response;
}

The SessionTokenInterceptor is added as an application interceptor and the LoggingInterceptor is added as a network interceptor because of the obvious reasons. The same is depicted through the below-mentioned code snippet.

由于明显的原因, SessionTokenInterceptor被添加为应用程序拦截器,而LoggingInterceptor被添加为网络拦截器。 通过下面提到的代码片段描述了相同的内容。

client = new OkHttpClient.Builder()
.addInterceptor(new SessionTokenInterceptor())
.addNetworkInterceptor(new LoggingInterceptor())
.build();

You will observe that the access token attached through the SessionTokenInterceptor(added as an application interceptor) is sent to the redirects in the below-mentioned logs and this is how you might be leaking user’s access tokens to third-parties.

您将观察到通过SessionTokenInterceptor (作为应用程序拦截器添加)附加的访问令牌已发送到下面提到的日志中的重定向,这就是您可能将用户的访问令牌泄漏给第三方的方式。

2020-02-27 16:35:17.143 9877-9953/com.example.okhttpinterceptorissue I/Logging Interceptor: Sending request http://192.168.1.70:5000/redirect on Connection{192.168.1.70:5000, proxy=DIRECT hostAddress=/192.168.1.70:5000 cipherSuite=none protocol=http/1.1}
User-Agent: OkHttp Example
Auth: ThisIsASampleSecretSessionToken
Host: 192.168.1.70:5000
Connection: Keep-Alive
Accept-Encoding: gzip
2020-02-27 16:35:17.152 9877-9953/com.example.okhttpinterceptorissue I/Logging Interceptor: Received response for http://192.168.1.70:5000/redirect in 8.2ms
Content-Type: text/html; charset=utf-8
Content-Length: 279
Location: http://goidirectory.nic.in/index.php
Server: Werkzeug/0.15.6 Python/2.7.16
Date: Thu, 27 Feb 2020 08:35:18 GMT
2020-02-27 16:35:17.163 9877-9953/com.example.okhttpinterceptorissue I/Logging Interceptor: Sending request http://goidirectory.nic.in/index.php on Connection{goidirectory.nic.in:80, proxy=DIRECT hostAddress=goidirectory.nic.in/164.100.58.217:80 cipherSuite=none protocol=http/1.1}
User-Agent: OkHttp Example
Auth: ThisIsASampleSecretSessionToken
Host: goidirectory.nic.in
Connection: Keep-Alive
Accept-Encoding: gzip
2020-02-27 16:35:17.367 9877-9953/com.example.okhttpinterceptorissue I/Logging Interceptor: Received response for http://goidirectory.nic.in/index.php in 202.6ms
Date: Thu, 27 Feb 2020 08:34:42 GMT
Server: Apache
X-Frame-Options: SAMEORIGIN
Referrer-Policy: same-origin
Feature-Policy: microphone 'none'; payment 'none'; sync-xhr 'self'
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Set-Cookie: PHPSESSID=hdddiq459djqfadibfgjmattg6; path=/
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

Note: It may sound like the attack can not be directly exploited as the backend is supposed to send the redirects to external domains(third-parties) which is usually not expected. However, this can be clubbed with other attack vectors such as HTTP Request Smuggling wherein the attacker already poisoned the request queue and the backend servers sends the redirects to attacker’s domain.

注意:听起来好像不能直接利用攻击,因为后端应该将重定向发送到通常不期望的外部域(第三方)。 但是,这可以与其他攻击媒介(例如HTTP请求走私)结合在一起,其中攻击者已经使请求队列中毒了,后端服务器将重定向发送到攻击者的域。

减轻 (Mitigation)

As soon as I discovered this, I notified the OkHttp team and as per the OkHttp’s security team, the behaviour is intended and involves low risk.

我一发现,便通知OkHttp小组,并根据OkHttp的安全小组,此行为是有意的,并且风险低。

I think our next steps should be to encourage developers to use the Authorization header when using HTTP headers that contain secrets against backends that may redirect to an untrusted server.

我认为我们的下一步应该是鼓励开发人员在使用HTTP标头(包含针对可能重定向到不受信任的服务器的后端的秘密)的HTTP标头时使用Authorization标头。

Hence I thought of writing this blogpost to let devs know about the current behaviour after the approval from the security team.

因此,我想到编写此博客文章,以使开发人员在安全团队批准后知道当前行为。

They suggest that devs should use standard headers(Authorization and Cookies) to send the session identifiers instead of non-standard header names

他们建议开发人员应使用标准标头(授权和Cookies)发送会话标识符,而不是非标准标头名称

In case changing the name of auth header is difficult and the redirection is expected, I suggest disabling auto redirects usingfollowRedirects(false) and using an additional application interceptor to check if the response is a redirection response and continue the redirection if and only if the domain in the redirection response is an expected response.

万一更改auth标头的名称很困难并且需要进行重定向,我建议使用followRedirects( false )禁用自动重定向,并使用其他应用程序拦截器来检查响应是否为重定向响应,并仅在以下情况下继续重定向:重定向响应中的域是预期的响应。

翻译自: https://medium.com/bugbountywriteup/are-you-sure-that-youre-not-leaking-user-s-access-tokens-to-third-parties-da16d63faaf4

令牌提交的身份验证失败

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值