4.5.5.1-测试 OAuth 授权服务器弱点

测试 OAuth 授权服务器弱点

总结

OAuth 将用户的身份及其相应的访问权限存储在授权服务器 (AS) 中。AS 在 OAuth 流程中起着至关重要的作用,因为它授予客户端访问资源的权限。为了能够安全地执行此操作,它必须正确验证作为 OAuth 流程一部分的参数。

未能验证参数可能会导致帐户接管、未经授权的资源访问和权限提升。

测试目标

  • 识别 Authorization Server 中的弱点。

如何测试

为了测试 AS 的弱点,您的目标是:

  1. 检索用于授权的凭证。
  2. 通过强制浏览授予自己对任意资源的访问权限。
  3. 绕过授权。

测试重定向 URI 验证不足

如果 redirect_uri 未正确验证,则可以构建一个链接,其中包含指向攻击者控制的服务器的 URL。这可用于诱骗 AS 向攻击者发送授权码。在以下示例中, client.evil.com 被用作伪造的 redirect_uri.

https://as.example.com/authorize?client_id=example-client&redirect_uri=http%3A%2F%client.evil.com%2F&state=example&response_mode=fragment&response_type=code&scope=openid&nonce=example

如果用户在 User Agent 中打开此链接,AS 会将 User Agent 重定向到恶意 URL。

攻击者可以捕获在欺骗性 URL 中传递的 code 值,然后将其提交到 AS 令牌终端节点。

以下请求说明了将 redirect_uri发送到授权服务器的授权请求。客户端 client.example.com使用 URL 编码的重定向 URI http%3A%2F%2Fclient.example.com%2F向 AS as.example.com 发送授权请求。

GET /authorize
    ?redirect_uri=http%3A%2F%2Fclient.example.com%2F
    &client_id=example-client
    &errorPath=%2Ferror
    &scope=openid%20profile%20email
    &response_type=code
    &response_mode=query
    &state=example
    &nonce=example
    &code_challenge=example
    &code_challenge_method=S256 HTTP/1.1
Host: as.example.com

AS 使用包含授权代码的重定向进行响应。这可以与 token 请求中的访问令牌进行交换。如下所示,Location 标头中的 URL 是上一个 redirect_uri 参数中给定的 URI。

HTTP/1.1 302 Found
Date: Mon, 18 Oct 2021 20:46:44 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 340
Location: http://client.example.com/?code=example&state=example

要测试 AS 是否容易受到重定向 URI 验证不足的影响,请使用 HTTP 拦截代理(如 ZAP)捕获流量。

  1. 启动 OAuth 流,并在授权请求处暂停它。
  2. 更改 redirect_uri 的值并观察响应。
  3. 调查响应并确定 AS 是否接受了任意 redirect_uri 参数。

如果 AS 将用户代理重定向到您指定的 redirect_uri ,则 AS 不会正确验证redirect_uri.

此外,Common Filter Bypass 请参阅测试服务器端请求伪造 中的部分,以识别重定向 URI 验证的常见绕过。

测试授权码注入
在授权代码流代码交换期间,AS 会向客户端颁发代码,然后与令牌终端节点交换代码,以检索授权令牌和刷新令牌。

对 AS 执行以下测试:

  1. 发送另一个 client_id .
  2. 为其他资源所有者发送有效代码。
  3. 发送另一个 client_id .
  4. 多次重新发送代码 (代码重播)。
测试公共客户端

发送到令牌终端节点的请求包含授权代码。它与令牌进行交换。使用 HTTP 拦截代理(如 ZAP)捕获此请求,并使用修改后的值重新发送请求。

POST /oauth/token HTTP/1.1
Host: as.example.com
[...]

{
    "errorPath":"/error",
    "client_id":"example-client",
    "code":"INJECT_CODE_HERE",
    "grant_type":"authorization_code",
    "redirect_uri":"http://client.example.com"
}

如果 AS 响应 access_token ,则代码已成功注入。

测试机密客户端

由于机密客户端的 OAuth 流还受客户端密钥保护,因此无法直接向令牌终端节点提交授权代码。相反,请将授权代码注入客户端。然后,此注入的代码将在令牌请求中发送,由机密客户端与客户端密钥一起颁发。

首先,从 AS 捕获授权码:

  1. 使用用户 Alice 启动授权代码流。当您收到来自 AS 的代码时暂停。
  2. 请勿将代码提交给客户端,并记下代码和相应的状态。

然后,注入代码:

  1. 使用用户 Mallory 启动授权代码流,并将之前为用户 Alice 收集的代码和状态值注入到流程中。
  2. 当攻击成功时,客户端现在应该拥有 一个 authorization_token允许访问用户 Alice 拥有的资源。
GET /callback?code=INJECT_CODE_HERE&state=example HTTP/1.1
Host: client.example.com
[...]

测试 PKCE 降级攻击

在某些情况下,可以从授权代码流中删除 PKCE 扩展。这可能会使公共客户端容易受到 PKCE 扩展缓解的攻击。

这可能在以下情况下发生:

  • AS 不支持 PKCE。
  • AS 未正确验证 PKCE。

两者都可以使用 ZAP 等 HTTP 拦截代理进行测试。执行以下测试:

  1. 发送不带 code_challenge=sha256(xyz) and code_challenge_method 参数的授权请求。
  2. 发送 code_challenge=sha256(xyz) 参数为空值的授权请求。
  3. 发送授权请求,并为 code_challenge=sha256(xyz)参数提供伪造值

以下示例突出显示了要修改的值:

GET /authorize
    ?redirect_uri=http%3A%2F%client.example.com
    &client_id=example-client
    &errorPath=%2Ferror
    &scope=openid%20profile%20email
    &response_type=code
    &response_mode=web_message
    &state=example-state
    &nonce=example-nonce
    &code_challenge=MODIFY_OR_OMIT_THIS
    &code_challenge_method=MODIFY_OR_OMIT_THIS
    &prompt=none HTTP/1.1
Host: as.example.com
[...]

AS 应验证令牌交换中的 code_verifier 值。要测试:

  1. 发送不带code_verifier的令牌请求。
  2. 发送带有空code_verifier的令牌请求。
  3. 使用针对不同授权代码的有效code_verifier 发送令牌请求。
POST /oauth/token HTTP/1.1
Host: as.example.com
[...]

{
"client_id":"example-client",
"code_verifier":"MODIFY_OR_OMIT_THIS",
"code":"example",
"grant_type":"authorization_code",
"redirect_uri":"http://client.example.com"
}

测试用户意见征求页面跨站点请求伪造

CSRF 攻击在 CSRF中描述。OAuth 可以使用 CSRF 进行攻击。

为了防止 CSRF 攻击 OAuth,利用 state参数作为反 CSRF 令牌。

其他措施也可以防止 CSRF 攻击。PKCE 流缓解 CSRF。nonce值也可以充当 anti-CSRF 令牌。

根据 CSRF 测试用例中描述的测试,测试包含 OAuth 使用的反 CSRF 参数之一的每个请求。

将向用户显示同意页面,以验证此用户是否同意代表用户访问资源的客户端。使用 CSRF 攻击同意页面可能会代表用户授予任意客户端对资源的访问权限。此流程的步骤如下:

  1. Client 生成一个 state 参数,并将其与同意请求一起发送。
  2. User Agent 将显示同意页面。
  3. 资源所有者向客户端授予访问权限。
  4. 同意将与已确认的范围一起发送到 AS。

使用 ZAP 等 HTTP 拦截代理来测试 state 参数是否经过正确验证。

POST /u/consent?state=Tampered_State HTTP/1.1
Host: as.example.com
[...]

state=MODIFY_OR_OMIT_THIS
&audience=https%3A%2F%2Fas.example.com%2Fuserinfo
&scope%5B%5D=profile
&scope%5B%5D=email
&action=accept

点击劫持测试

点击劫持测试中介绍了点击劫持。当同意页面容易受到点击劫持,并且攻击者拥有client_id(对于公共客户端,或机密客户端的客户端密钥) 时,攻击者可以伪造用户的同意,并通过流氓客户端获得对所请求资源的访问权限。

如何测试

要使此攻击成功,攻击者需要在 iframe 中加载授权页面。

以下 HTML 页面可用于在 iframe 中加载授权页面:

<html>
    <head>
        <title>Clickjack test page</title>
    </head>
    <body>
        <iframe src="http://as.example.com/auth/realms/example/login-actions/required-action?execution=OAUTH_GRANT&client_id=example-client" width="500" height="500"></iframe>
    </body>
</html>

如果成功加载,该网站容易受到点击劫持。

有关如何进行此类攻击的详细说明,请参阅点击劫持测试

测试 Token Lifetime

OAuth 有两种类型的令牌:访问令牌和刷新令牌。访问令牌的有效期应受到限制。这意味着它是短暂的:一个好的持续时间取决于应用程序,可能是 5 到 15 分钟。

刷新令牌的有效期应较长。它应该是一次性令牌,每次使用时都会替换它。

测试访问令牌生命周期验证

当 JSON Web 令牌 (JWT) 用作访问令牌时,可以从解码的 JWT 中检索访问令牌的有效性。这在测试 JSON Web 令牌中进行了介绍。AS 可能无法正确验证 JWT 的生存期。

要测试访问令牌的生存期,请使用 HTTP 拦截代理,例如 ZAP。拦截对包含访问令牌的终端节点的请求。将此请求放入 repeater 中,让目标时间过去。访问令牌的有效期应介于 5 到 15 分钟之间,具体取决于资源的敏感度。

此类请求可能类似于以下示例。令牌还可以通过其他方式传输,例如,在 Cookie 中。

GET /userinfo HTTP/1.1
Host: as.example.com
[...]
Authorization: Bearer eyJhbGciOiJkaXIiL[...]

通过在经过不同时间长度(例如,5 分钟、10 分钟和 30 分钟后)发送请求来测试生命周期验证。

可以通过自动执行服务器响应的步骤和日志记录来优化此过程。当收到 HTTP 状态 403(而不是 HTTP 状态 200)的响应时,这可能表示访问令牌不再有效。

测试刷新令牌生命周期验证

刷新令牌的有效期比访问令牌长。由于它们的有效期很长,因此在与访问令牌进行交换后,它们应该失效。

刷新令牌在将访问令牌分发给客户端的同一令牌请求中颁发。

使用 HTTP 拦截代理,例如 ZAP。通过执行以下操作来设置测试:

  1. 检索有效的刷新令牌。
  2. 捕获用于将刷新令牌与新访问令牌交换的请求。
  3. 将捕获的请求发送到请求转发器。

在以下示例中,刷新令牌作为 POST 正文的一部分发送。

POST /token HTTP/1.1
Host: as.example.com
Cookie: [...]
[...]

grant_type=refresh_token
&refresh_token=eyJhbGciOiJIUz[...]
&client_id=example-client

执行以下测试:

  1. 发送刷新令牌并确定 AS 是否分发访问令牌。
  2. 使用相同的刷新令牌重复这些步骤,以评估接受单个刷新令牌的频率。

当 JWT 用作刷新令牌时,可以从解码的 JWT 中检索刷新令牌的有效性。这在测试 JSON Web 令牌中进行了介绍。刷新令牌的有效期可能较长,但应具有到期日期。

通过盗窃检测机制可以获得额外的安全性。如果在令牌交换中使用刷新令牌的时间超过其有效期(或生命周期),则 AS 会使所有刷新令牌失效。要测试此机制,请执行以下操作:

  1. 发送刷新令牌并确定 AS 是否分发访问令牌。
  2. 使用相同的刷新令牌重复这些步骤,直到它失效。
  3. 使用上次令牌响应中的刷新令牌

如果为此资源所有者颁发给客户端的所有刷新令牌都无效,则 AS 将进行令牌盗窃检测。

相关测试用例

修复

大多数针对 OAuth AS 的攻击可以通过在授权代码和令牌交换期间验证参数的存在和内容来缓解。

限制授权码和刷新令牌等凭证的时间跨度和允许使用。这可以缓解某些类型的攻击,还可以限制攻击者对此类凭证的使用(如果已获得这些凭证)。

正确配置安全缓解措施,如 CORS、反 CSRF 令牌和反点击劫持标头,可以减轻或限制攻击的影响。

  • 始终验证所有参数是否都存在,并验证其值。
  • 使用 PKCE 扩展来正确保护授权码和令牌交换。
  • 不允许 PKCE 扩展等安全功能的回退。
  • 限制凭据的生存期。
  • 尽可能只使用一次凭证,例如授权码。
  • 配置可用的安全缓解措施,如 CORS、防 CSRF 令牌和防点击劫持标头。

工具

引用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值