预接管漏洞挖掘:条件竞争与逻辑缺陷的组合利用

预接管漏洞挖掘:条件竞争与逻辑缺陷的组合利用

原创 漏洞集萃 漏洞集萃 2025-05-30 08:56


大家好!在这篇分享中,我将详细讲述我如何发现一个应用程序中的逻辑漏洞和竞争条件,并利用它们最终实现了账户预接管(Pre-Account Takeover,简称 Pre-ATO)。这个漏洞能让攻击者在无需用户任何交互
的情况下,完全劫持受害者的账户,并且,用户无法自行恢复其账户

让我们先来理解一下这个应用程序的工作流程:

这款应用允许用户通过两种方式注册:
1. 传统的邮箱和密码
方式

  1. 谷歌 SSO
     (Single Sign-On,单点登录)

如果用户使用普通的邮箱和密码注册,他们可以在账户设置中更改自己的邮箱地址。

然而,如果用户是通过谷歌 SSO 注册的,前端界面会禁用更改邮箱的选项。

但这仅仅是前端的限制。那么,后端是怎么处理的呢?

我尝试在用普通邮箱注册的账户中更改邮箱,并拦截了请求包,发现其中有这样一个参数:“user%5Bemail%5D
”。

于是,我灵机一动,尝试在我用谷歌 SSO 登录的账户进行任意一项资料修改(比如修改用户名)时,在请求中手动添加上同样的参数,并将其值设置为 [email protected]

你们猜,我发现了什么?!

服务器返回了一个 302 Found
 的响应,这意味着邮箱更改的请求被接受了!

但这里有一个小问题…

应用程序会向新的邮箱地址(即 [email protected]
)发送一封确认邮件。在受害者点击确认链接之前,攻击者是无法真正接管账户的。

到这一步,我们需要想办法绕过这个邮件确认环节。

所以我尝试了一些技巧,比如篡改响应包,或者尝试把验证码发送到另一个邮箱,但都没有成功。所以,在那个时候,我感觉自己有点束手无策了。

我想,要不就这么报告上去吧,估计会因为需要用户交互而被判定为低危漏洞。但是,这个漏洞的实际影响是什么呢?

如果用户真的点击了那封确认邮件,那么攻击者就能完全访问受害者的账户(因为邮箱已经变成了受害者的邮箱,但登录方式还是攻击者的谷歌账户)。并且,受害者将无法再使用这个邮箱注册新账户,也无法登录,因为它已经和攻击者的谷歌账户绑定了。

当受害者尝试通过“忘记密码”来找回与该邮箱关联的账户时,他会发现:

于是,我把这个发现报告给了 HackerOne,心里想着它大概率会被评为低危。

两周后,我收到了这样的回复:

好吧,所以我接受了这个挑战,决心要绕过那个确认邮件。

我向我的朋友 Mahmoud 求助,我们一起开始测试各种不同的绕过技术:比如 Host 头部攻击,操纵邮件参数,尝试将确认链接或验证码发送给攻击者自己的邮箱,或者在点击发送给受害者的确认链接时,在请求中把邮箱参数再改回受害者的邮箱等等……但都失败了。

然后,我突然想到:为什么不试试竞争条件 (Race Condition) 呢???

这个想法其实很简单:
1. 同时发送两个更改邮箱的请求:一个请求将邮箱改为 [email protected]
,另一个请求将邮箱改为 [email protected]

  1. 如果时机掌握得恰到好处,系统在处理这两个几乎同时到达的请求时,可能会发生混乱,从而错误地确认了本不该确认的邮箱。

想到这里,我立即将这两个请求添加到了 Burp Repeater 的一个请求组 (group) 中,并设置为并行发送 (send in parallel)。

结果你猜我发现了什么?确认邮件同时发送给了 [email protected]
 和 [email protected]
 这两个账户。 当我点击发送给 [email protected]
 的那个链接时,页面提示 “链接无效,请重试”。

而当我点击发送给 [email protected]
 的那个链接时,却提示 “邮箱已确认”!

我赶紧回到应用程序,刷新了一下页面,惊喜地发现我的账户邮箱已经变成了 “[email protected]
”!

我请我的朋友 Mahmoud 帮忙确认了这个发现,并录制了 PoC 来更新我们之前提交的报告。

大约一个月后,HackerOne 那边有了回复:

复现步骤 (Steps to Reproduce)
1. 用你自己的谷歌账户注册并登录该应用。

  1. 导航到 设置 (Settings) → 修改你的姓名 (Modify your name) → 点击 保存 (Save)。

  2. 用 Burp Suite 拦截这个保存姓名的请求。

  3. 将这个请求发送到 Repeater 模块两次。在第一个请求中添加参数 &user%5Bemail%[email protected]
    ,在第二个请求中添加参数 &user%5Bemail%[email protected]

  4. 请求1 payload: (&user%5Bemail%[email protected])

  5. 请求2 payload: (&user%5Bemail%[email protected])

  6. 将这两个请求添加到一个 Burp Repeater 的请求组中,并选择并行发送 (Send Parallel),以制造竞争条件。

  7. 受害者邮箱 ([email protected]
    ) 和攻击者邮箱 ([email protected]
    ) 都会收到一封邮件验证请求。

  8. 攻击者只点击自己邮箱 ([email protected]) 收到的那封验证链接

  9. 由于竞争条件的存在,系统会错误地将攻击者谷歌账户关联的邮箱更新为 [email protected]
    (即受害者的邮箱),尽管攻击者点击的是发送给自己邮箱的链接。

  10. 登出账户,然后使用你的谷歌 SSO 重新登录。你会发现,你现在已经完全登录到了邮箱为 [email protected]
     的账户中,实现了账户接管。

====本文结束====

以上内容由漏洞集萃翻译整理。

参考:

https://medium.com/@yassentaalab51/race-condtion-logic-bug-lead-to-pre-ato-4fb85dfb4bcc