SigninwithApple0day复盘:十万美元赏金背后的认证绕过

admin 2026-09-04 04:49:37 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文复盘2020年SigninwithApple认证绕过0day漏洞,攻击者仅凭邮箱即可完全接管第三方应用账户。根因是验签通过不等于断言成立,JWT签名不保证签发方验证过邮箱所有权。文章纠正两处误传:该漏洞无CVE编号,且作者未测试所列厂商。建议以sub而非email作为账户关联主键,并对社交登录身份增加额外验证。 综合评分: 88 文章分类: 漏洞分析,WEB安全,安全大事件


Sign in with Apple 0day 复盘:十万美元赏金背后的认证绕过

Ots安全

2026年9月1日 12:43 广东

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

威胁简报

恶意软件

漏洞攻击

前言

2020 年 5 月 30 日,安全研究员 Bhavuk Jain 公开了一篇很短的博客,标题是 Zero-day in Sign in with Apple。全文不到一千字,讲的事情却足够惊人:

只要知道你的邮箱地址,他就能接管你在第三方应用里的账户。

这个漏洞在 2020 年 4 月被发现并报告给 Apple,5 月底修复,苹果给研究者支付了十万美元赏金,服务器日志排查后确认没有被在野利用。到今天,它已经修复六年了。

那为什么还要写它。

因为它把一个在联邦身份认证里反复出现的混淆讲得特别干净:验签通过,不等于断言成立。JWT 上的签名能证明这个 token 确实是 Apple 签的、内容没被改过,但它不能证明 Apple 在签发之前验证过”这个邮箱属于你”。第三方应用看到签名有效,又看到 payload 里写着 email_verified: true,很自然会认为所有权验证已经做过了。而实际上,那一步从来没有发生过。

六年过去,同样的混淆还在各种 OIDC 与 SAML 实现里重演,换的只是字段名和厂商名。

本文做两件事。第一件是把机理与影响范围讲准,尤其是两处流传很广的误传需要纠正。第二件是把它沉淀成一份可以对照执行的检查清单,无论你今天接的是哪家身份提供方,都用得上。

先说清楚那两处误传,因为它们直接关系到这篇文章该怎么被引用。

第一,网上大量中英文资料把 CVE-2020-9859 说成这个漏洞的编号。这是错的。Apple 官方安全公告里,CVE-2020-9859 是 iOS 13.5.1 修复的一个内核内存消耗问题,可导致应用以内核权限执行任意代码,致谢对象是 unc0ver。它与 Sign in with Apple 毫无关系。这个漏洞没有公开的 CVE 编号。

第二,原文提到 Dropbox、Spotify、Airbnb、Giphy 等应用使用了该功能,但作者紧接着明确写了这些应用他没有测试过。后文会把这一点展开。

一、漏洞事实:只需要一个邮箱

先把事实摆齐。

发现与披露。 Bhavuk Jain 于 2020 年 4 月发现该问题,在公开披露之前已向 Apple 报告。Apple 于同年 5 月底完成服务端修复。5 月 30 日,作者发布技术博客。6 月 1 日,ZDNet 等媒体报道。

漏洞性质。 身份认证绕过,后果是完全账户接管(full account takeover)。原文的表述是,攻击者可以针对第三方应用上的用户账户实施完全接管,而且与受害者是否拥有有效的 Apple ID 无关

攻击所需。 一个邮箱地址。不需要密码,不需要第二因素,不需要接触受害者的设备,不需要受害者做任何操作。

赏金与处置。 作者经 Apple Security Bounty 计划提交报告,获得 $100,000 赏金。Apple 排查了服务器日志,结论是没有发现因该漏洞导致的滥用或账户泄露。修复在服务端完成,第三方应用不需要更新

一次处置相当标准的流程,大额赏金、快速修复、日志排查、研究者等到修复后再公开。这几方面都值得学习,尤其是研究者等到修复落地才发博客这一条,中间隔了将近一个月。

二、机理拆解:正常流程与那条没走的路

2.1 正常流程是什么样的

Sign in with Apple 的工作方式与 OAuth 2.0 类似。认证用户可以通过两条路完成:一是直接用 Apple 签发的 JWT(JSON Web Token),二是先用 Apple 服务器生成的 code,再用 code 去换 JWT。

流程中间有一个关键设计,也是这个功能主打的隐私卖点:授权时,Apple 会给用户一个选择,可以把真实 Apple 邮箱分享给第三方应用,也可以隐藏。如果选择隐藏,Apple 会生成一个该用户专属的中继邮箱,形如 [email protected]

无论用户选哪一种,授权成功之后,Apple 都会创建一个 JWT,里面包含这个邮箱地址。第三方应用拿着这个 JWT 来登录用户。

2.2 JWT 里到底写了什么

原文给出了一个解码后的 payload 样例:

{
  "iss": "https://appleid.apple.com",
  "aud": "com.XXXX.weblogin",
  "exp": 158XXXXXXX,
  "iat": 158XXXXXXX,
  "sub": "XXXX.XXXXX.XXXX",
  "c_hash": "FJXwx9EHQqXXXXXXXX",
  "email": "[email protected]",
  "email_verified": "true",
  "auth_time": 158XXXXXXX,
  "nonce_supported": true
}

逐项看一遍,因为后面会用到:

  • iss

    是签发者,这里是 https://appleid.apple.com

  • aud

    是受众,也就是目标应用的 client id

  • exp

    与 iat 是过期时间与签发时间

  • sub

    是用户在该应用下的唯一标识

  • c_hash

    是授权码的哈希,用于把 JWT 与同一次授权绑定

  • email

    是用户选择分享的邮箱,可能是真实邮箱,也可能是中继邮箱

  • email_verified

    表明该邮箱是否已被验证

  • auth_time

    是认证发生的时间

  • nonce_supported

    表明客户端是否支持 nonce

这里有两个字段要记牢,一个是 sub,一个是 email_verified。后文会讲它们在整件事里分别扮演什么角色。

2.3 出问题的那一步

原文对这个 bug 的描述只有两句话:

I found I could request JWTs for any Email ID from Apple and when the signature of these tokens was verified using Apple's public key, they showed as valid.

意思是,他可以向 Apple 请求针对任意邮箱的 JWT,而这些 token 用 Apple 的公钥验签时,全都显示为有效

作者贴出了那一步的请求与响应(已脱敏)。请求是一个发往 appleid.apple.com 的 POST,消息体里只有一个 email 字段。响应里带着签发好的 id_token、一个 grant_code、授权的 scope,以及用户标识 userId

关键在响应的末尾那一行"consentRequired" : false

2.4 consentRequired 为 false 意味着什么

这一行是整个漏洞的注脚。

consentRequired 为 false,表示这次授权不需要征得用户同意。也就是说,攻击者拿着受害者的邮箱,向 Apple 发一个请求,就拿到了一份 Apple 亲自签名、验签必然通过、里面写着”这个邮箱已验证”的身份凭证。

整个过程中,没有任何一个环节要求攻击者证明自己拥有这个邮箱。没有发验证邮件,没有要求登录 Apple ID,没有短信或设备确认。用户甚至不会收到任何提示。

于是回到开头那句话:只要知道你的邮箱地址,就够了。

把 consentRequired: false 与”任意 email 可提交”放在一起看,问题就非常直白了。前者让流程不需要用户参与,后者让攻击者可以指定任意身份,两者叠加,加上 Apple 的签名作为背书,一个完全无需受害者的账户接管链路就闭合了。

三、根因:验签通过,不等于断言成立

漏洞本身讲完了,接下来是它真正值得被记住的部分。

3.1 签名保证什么,不保证什么

JWT 的签名解决的是两个问题:

其一,来源可信。这个 token 确实由持有 Apple 私钥的一方签发,不是别人伪造的。

其二,完整性。token 从签发到到达应用手里,内容没有被改过。

这两件事签名都能保证,而且保证得很扎实。

但有一件事它不保证:签发方在签发之前,做过哪些业务层面的验证。

签名是一个密码学操作,它对”Apple 有没有验证过这个邮箱属于请求者”这件事完全无感。它只负责把 Apple 写下的内容原封不动地封起来,并且让所有人都能确认这确实是 Apple 写的。

3.2 email_verified 这个字段的信任陷阱

应用侧为什么会中招,看 payload 里那个字段就明白了。

email_verified: "true"

从应用开发者的视角看,这个字段的语义是明确的:这个邮箱已经被验证过了。既然是 Apple 签的,那自然是 Apple 验证的。既然 Apple 说验证过了,那我就可以放心地认为”当前登录的人拥有这个邮箱”。

于是应用的账户关联逻辑会这样写:收到 JWT,验签通过,取出 email,去用户表里找这个 email 对应的账户,找到了就登录为那个用户。

攻击者伪造的 JWT 走的就是这条路。验签通过,email_verified 是 true,email 是受害者的邮箱,用户表里一查就命中受害者的账户,登录成功。

每一个技术步骤都正确执行了,结论却是错的。

3.3 抽象:身份提供方断言的语义边界

把这件事抽象一层,就是联邦身份体系里一个根本性的设计问题:

身份提供方(IdP)的每一条断言,都需要有明确定义的语义,而消费方必须准确理解这个语义。

email_verified 这个字段,应用的解读是”Apple 已验证该邮箱归属于当前认证主体”。而 Apple 的实际语义,在这个漏洞存在的时期,更接近”这个邮箱字段已按要求填入”。两者的差距,就是整个漏洞。

这类问题的通用形态是:消费方对断言的解读,比签发方的实际保证更强

它不局限于 email。类似的还有:

  • 把”该用户在此 IdP 存在”读成”该用户在此 IdP 完成了强认证”
  • 把”该用户有此邮箱”读成”该用户已确认拥有此邮箱”
  • 把”该用户在此租户有记录”读成”该用户当前有权限访问本应用”

每一种误读都对应一类真实存在过的漏洞。

3.4 为什么六年过去这类问题还在重演

有几个结构性原因。

其一,IdP 的文档通常只描述字段格式,很少描述失败模式。文档会告诉你 email_verified 是一个字符串或布尔值,但不一定会写清楚”在哪些情况下它可能为 true 但不代表所有权已验证”。

其二,集成方倾向于实现”能跑通”的最小路径。验签、取出 email、关联账户,这条路径能跑通,于是就停在这里了。去深究每个字段的确切语义,需要额外的成本,而且短期看不出收益。

其三,这类 bug 在测试里几乎不可能被发现。正常情况下,JWT 里带的邮箱确实是认证用户自己的邮箱,关联也确实关联对了。只有攻击者才会提交一个不属于自己的邮箱,而这是测试不会覆盖的场景。

技术点评:密码学层面的正确,替代不了业务语义层面的正确。验签是一道必要的防线,但它守护的是”消息没被伪造”,不是”消息说的是真话”。后者需要签发方与消费方对每条断言的语义达成一致,而这个一致性,目前主要靠文档与约定来维持,缺少机制上的强制。

四、影响范围核实

这一节是全文的重心。这个案例在二手传播里失真严重,需要逐项厘清。

4.1 两层责任:漏洞在一侧,伤害在另一侧

理解影响范围,关键是把两层拆开。

第一层,Apple 侧,漏洞本体。 授权接口接受任意提交的 email 并签发有效 id_token,全程无所有权验证,且 consentRequired 为 false。这是一个服务端的、纯粹的实现缺陷,Apple 修复后即消除,应用无法自行规避。

第二层,第三方应用侧,伤害放大。 漏洞能否转化为账户接管,取决于应用怎么用这个 JWT。两种做法会显著放大风险:

  • 以 email 作为账户关联主键。攻击者伪造的 JWT 里 email 是受害者的,一查就命中已有账户。
  • 信任 email_verified 之后不再做二次校验。应用认为验证已经由 Apple 完成,于是不再发验证邮件、不再比对已有记录。

原文对受影响对象的定义很精确:使用该功能,且未实现自己额外安全措施的第三方应用

4.2 哪些应用受影响:条件是”没加额外校验”

这里要特别注意一个限定词,”未实现额外安全措施”。

如果应用做了下面任何一件事,攻击就不成立或至少大幅受限:

  • 以 sub 而非 email 作为关联主键,且账户初次关联发生在可信流程内
  • 对首次出现的社交登录身份要求额外的邮箱验证
  • 不把社交登录身份与已有邮箱账户自动合并

反过来说,那些”收到 JWT、取 email、直接关联已有账户”的应用,就处在这次的影响范围内。

4.3 作者列举的厂商:明确未测试

原文提到使用该功能的应用,举了 Dropbox、Spotify、Airbnb、Giphy(当时已被 Facebook 收购)为例。

但作者紧接着写了一句非常关键的话,大意是:这些应用没有经过测试,如果在验证用户时没有其它安全措施,它们可能容易受到完全账户接管的影响。

这句话有两层意思。第一,这些公司对作者而言只是”已知使用了该功能”的例子,不是已确认的受害者。第二,是否受影响取决于它们各自的额外校验,作者不知情。

因此本文不做这样的表述:这些公司被确认受影响。 把它们写成”曾被认为可能受影响、但从未被测试或确认”,才是准确的。

4.4 不需要受害者有 Apple ID

这一点经常被漏掉,但它极大地扩大了潜在受害者面。

原文的表述是,这次完全账户接管可以发生,与受害者是否拥有有效的 Apple ID 无关

原因在于,攻击者触发的是 Apple 签发环节的一个缺陷,而不是受害者账户的某个属性。只要受害者在某个第三方应用上用某个邮箱注册了账户,而那个应用接了 Sign in with Apple 且没加校验,攻击者就能用这个邮箱去 Apple 换一份有效凭证。

受害者可以从来没用过 Apple 设备,可以根本没有 Apple ID,甚至可能不知道自己的邮箱被用在了这条链路里。

4.5 强制集成带来的广度

这个功能在 iOS 生态里的普及程度,有一个制度性原因。

根据 App Store 的审核规则,凡是支持第三方社交登录的应用,必须同时提供 Sign in with Apple。这一条让它在 iOS 生态里接近于标配,集成面远超一个普通的登录选项。

这也解释了原文那句感叹:很多开发者集成了它,因为它是强制要求。强制集成意味着大量应用是在”为了满足审核”的心态下接入的,这类接入往往采用最简实现,也就是最容易踩中 Section 4.1 那两条放大条件的那种实现。

4.6 必须纠正的误传:CVE-2020-9859

这一条值得单独拿出来,因为它在中文技术资料里流传很广。

不少文章把这个漏洞标注为 CVE-2020-9859。查 Apple 官方安全公告(iOS 13.5.1 与 iPadOS 13.5.1 的安全内容),原文记载如下:

Kernel … Impact: An application may be able to execute arbitrary code with kernel privileges. Description: A memory consumption issue was addressed with improved memory handling. CVE-2020-9859: unc0ver

也就是说,CVE-2020-9859 是一个内核内存消耗问题,后果是应用可能以内核权限执行任意代码,由 unc0ver 相关,修复于 iOS 13.5.1,与 Sign in with Apple 没有任何关系。

而本次漏洞,原文没有提 CVE,ZDNet 的报道也没有提。本文的结论是:这个漏洞没有公开的 CVE 编号。

原因不难推测。Apple 是在服务端完成修复的,第三方应用无需更新,用户无需操作。这类服务端修复通常不会进入 Apple 的产品安全公告体系,也就没有 CVE。

技术点评:引用一个漏洞时,编号是硬事实,编错了会让整篇文章的可信度崩塌。二手资料里的编号应当回查官方来源,尤其是当这个编号来自另一份完全不同的产品公告时。

4.7 关于 iCloud 数据泄露的猜测:没有证据

ZDNet 在报道中提到一句,大意是也有人提出,这个问题的范围可能还会导致 iCloud 账户数据泄露。

这个说法需要正确对待。它是一个被提出的猜测,不是作者的结论,不是 Apple 的确认,也没有任何证据支持。原文只谈第三方应用的账户接管,只字未提 iCloud。

本文不把它当作影响范围的一部分,只在此说明曾有此一说,且至今没有证据。

4.8 当前状态:已修复六年

还有一点必须说清楚,因为它决定了读者该怎么处置。

这个漏洞在 2020 年 5 月底由 Apple 在服务端修复,距今已六年。当前使用 Sign in with Apple 的应用与用户,不受这个问题影响。

因此本文的定位是复盘与教训提炼,不是风险预警。读者需要做的不是应急响应,而是检查自己今天的身份集成实现里,有没有犯同样的错。

五、自查与加固

前面讲完机理和边界,这一节我们自己动手,把这件事变成一份可以对照执行的清单。这些条目不针对 Apple,对任何 OIDC 或 SAML 集成都适用。

5.1 先看账户关联主键用的是什么

这是本节最重要的一条,也是当年最能决定命运的一条。

打开你的账户关联逻辑,先确认一件事:社交登录进来之后,你用什么去匹配已有账户。

  • 如果用的是 email,风险较高。因为 email 在多数系统里不是稳定且独占的标识,它可能被改、被复用、被伪造。
  • 如果用的是 IdP 提供的 sub(subject),风险显著更低。因为 sub 由 IdP 保证在该应用下唯一且稳定,攻击者无法通过猜测拿到别人的 sub

Apple 官方文档一直推荐用 sub 作为用户标识。以 OIDC 的通用术语说,正确的做法是:iss 与 sub 组合起来构成全局唯一的用户标识,单独用 email 是不可靠的。

5.2 再验一次:消费 IdP 断言的六项检查

收到一个 id_token 之后,下面六项应该逐条检查,缺一项就留一道口子:

  1. 验签

    用 IdP 公开的 JWKS 密钥验证签名,注意密钥要按 kid 正确选取,并且要有轮换处理。

  2. 校验 iss

    确认签发者确实是你信任的那个 IdP,而不是任何别的、恰好也用同样格式的签发者。

  3. 校验 aud

    确认这个 token 是签给你的应用的。这一步能挡住”拿 A 应用的 token 去登录 B 应用”这类混淆。

  4. 校验 exp 与 iat

    确认在有效期内,且签发时间合理。

  5. 校验 nonce

    如果你在请求里带了 nonce,回来必须比对,这是防重放的关键一环。

  6. 确认 email_verified 的真实语义

    这一步最容易被跳过。你需要知道你的 IdP 在什么条件下会把这个字段置为 true,以及这个条件是否等价于你要的”所有权已验证”。如果不确定,就自己再发一次验证邮件。

5.3 账户合并策略是高危设计点

很多账户接管问题,最终都落在”合并”这一步。

典型场景:用户用邮箱注册了账户,后来用社交登录进来,系统发现 email 相同,于是自动合并。或者反过来,社交登录创建了账户,后来用户用邮箱密码登录,系统发现 email 相同,自动合并。

自动合并的诱惑在于体验顺畅,代价在于它把”email 相同”当成了”是同一个人”的充分证据。而 email 相同这件事,攻击者在很多场景下都能做到。

更稳妥的做法:

  • 首次社交登录进来,创建独立身份,不要自动合并
  • 如果检测到 email 与已有账户相同,要求先完成对已有账户的认证(输入密码、接收验证邮件),再手动确认合并
  • 合并动作记录日志,并对用户发出通知

5.4 一份通用的第三方登录集成清单

把上面几条汇总,再加几条,形成一份可以贴到评审表里的清单:

  • 用 iss + sub 作为用户唯一标识,不要用 email
  • 完整执行六项 token 校验,不跳项
  • 不自动合并身份,合并前要求对已有账户完成认证
  • 不把 IdP 返回的任意字段直接当作已验证事实使用,逐一确认语义
  • 登录流程服务端实现,不把 token 校验逻辑放在客户端
  • 对登录失败、异常关联、重复绑定等行为记录日志并设告警
  • 定期轮换客户端密钥,密钥不进代码仓库
  • 关注 IdP 的安全公告与 JWKS 端点变更

5.5 怎么判断自己现在的实现

如果你接了任意一家社交登录,可以用下面三处检查点快速自查:

第一处,关联主键。 在数据库里查用户表与第三方绑定表,看关联字段是 email 还是 provider 加 sub 的组合。如果看到 email,标记为待改。

第二处,aud 与 nonce。 这两项是最常被跳过的。翻一下 token 校验的代码,如果只验签就取字段,标记为待改。

第三处,身份合并是否自动。 搜一下合并逻辑,如果 email 相同就自动合并且没有任何额外认证,标记为高危。

这三处检查完,你的集成处在什么水位,基本就有数了。

技术点评:这份清单里没有一条需要高深的技术,难的是它们分散在不同的人手里,验签的归后端,关联的归账户系统,合并策略归产品。这类问题的根因往往不是不会做,而是没有人从头到尾看过一遍。

结束语

这个漏洞的技术形态一点都不复杂。攻击者提交一个邮箱,Apple 返回一份签好的凭证,凭证里写着这个邮箱已验证,应用信了,账户就丢了。

真正值得琢磨的是那道被默认跨越的界线。

签名这道工序,从密码学角度看完成得非常完美。它确实证明了这个 token 来自 Apple,确实证明了内容没有被篡改。问题在于,应用需要的保证不只是这个。应用需要的是”这个人拥有这个邮箱”,而签名从来没承诺过这件事。

于是每一个环节都正确执行了:Apple 签了它承诺签的内容,传输没有篡改,应用验签通过,字段读取正确,账户关联逻辑正常。每一步都对,结论却是有人丢了账户。

六年过去,具体的技术细节会过时,这个结构不会。只要还有系统在消费外部提供的身份断言,只要还有人默认把”来源可信”读成”内容为真”,同样的事情就会换个名字再来一次。

一个邮箱换一个账户。代价不大,前提是那道界线被看清楚。

END

公众号内容都来自国外平台-所有文章可通过点击阅读原文到达原文地址

公众号 | AnQuan7 (Ots安全)


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:Ots安全 《Sign in with Apple 0day 复盘:十万美元赏金背后的认证绕过》

安全能力池一点通 | 第4期 网络安全文章

安全能力池一点通 | 第4期

文章总结: 该文档为中国电信安全能力池产品线的宣传介绍文章,属于产品推广性质内容,主要展示排版人员信息及推荐阅读链接,未涉及具体技术细节或安全能力说明,内容较为
评论:0   参与:  0