Highlight
App Attest 利用 Secure Enclave(安全隔区)生成不可导出的硬件绑定密钥,为服务器提供加密证明,确认请求来自运行在真实 Apple 设备上的未篡改 App。iOS 27 新增 launch validation category 和 bundle version 扩展字段,macOS 27 首次支持并引入 ACL Blob OID 验证系统完整性,同时新增的 Fraud Metric 可检测一台设备在过去 30 天内生成过多密钥的异常行为。
核心内容
你做了一个在线考试 App,学生答题后把答案提交到服务器打分。攻击者反编译你的 App,做一个修改版,直接往服务器提交伪造的高分答案。你的服务器收到请求,看起来和正常请求一模一样,根本分辨不出来。
App Attest 就是用来解决这个问题的。
它的核心思路很简单:让设备上的 Secure Enclave 生成一对密钥,私钥永远留在硬件里,公钥的哈希作为 key ID 返回给 App。App 把这个 key ID 发给服务器,服务器下发一个 challenge,App 拿着 challenge 去请求 Apple 生成 attestation(证明)。这个 attestation 包含证书链、设备硬件快照、App 身份信息,服务器验证后就能确认:这个请求确实来自一个未篡改的 App,运行在真实的 Apple 设备上。
(01:53)以前防篡改靠越狱检测、设备指纹,和攻击者玩猫鼠游戏。App Attest 把信任根锚定在 Apple 硬件和 Secure Enclave 上,攻击者无法导出私钥,也无法在另一台设备上复用 attestation。
(02:15)除了证明设备真实,App Attest 还能暴露 App 是否被修改。它通过 relying party identifier(Team ID + Bundle ID 拼接)标识你的 App。攻击者重新签名后 Team ID 会变,attestation 里就能看出来。
(03:03)iOS 27 新增了两个重要信号:launch validation category 告诉你 App 是从 App Store、TestFlight 还是其他渠道启动的;bundle version 让你确认运行的是不是你发布的版本。攻击者升级 Bundle Version 重新签名,这些变化都会暴露在 attestation 里。
(04:08)macOS 27 首次支持 App Attest,这对 Mac 端的高价值业务(金融、游戏反作弊)意义重大。Mac 生态比 iOS 开放,用户可以关闭 SIP(System Integrity Protection)或降级安全策略。Apple 在 macOS 的证书链中加入了 ACL Blob OID,记录了生成密钥时设备是否处于 Full Security 模式和 SIP 开启状态。
(16:27)Fraud Metric 是这次最有意思的新能力。它回答了一个老问题:攻击者用几百台真机组成设备农场,每台都是真机,单看 attestation 根本拦不住。Fraud Metric 返回一台设备在过去 30 天内生成的唯一 attested key 数量的近似值。正常用户一台设备一个密钥,如果这个指标飙升,说明这台设备在批量生成凭证,或者被当作代理(broker)为其他设备签发 attestation。
详细内容
判断可用性
(04:26)App Attest 支持所有 Apple 平台,包括新加入的 macOS 27。但不是所有 App 类型都可用,需要通过 isSupported 判断:
import DeviceCheck
if DCAppAttestService.shared.isSupported {
// App Attest 可用,正常集成
} else {
// 标记为风控信号,限制敏感功能
}
关键点:
- Action 和 SSO App Extension 支持,其他类型 Extension 不支持
isSupported == false本身可以作为 fraud signal 纳入风险评估- 如果一台声称是 iPhone 15 的设备频繁返回不支持,可能已被篡改
生成密钥
(05:07)App 调用 generateKey() 生成 Secure Enclave 绑定的密钥对:
import DeviceCheck
let keyID = try await DCAppAttestService.shared.generateKey()
// 把 keyID 存入 Keychain
关键点:
- 私钥存储在 Secure Enclave,无法导出
- 每个用户生成一个密钥,或每台设备一个密钥,不要跨用户共享
- 密钥在 App 更新后仍然有效,但重装 App 或恢复设备(包括 iCloud 备份恢复)会失效
- 密钥不跨设备同步
请求 Attestation
(06:32)密钥生成后,App 向服务器请求 challenge,然后调用 attestation API:
import DeviceCheck
let keyId: String = fetchKeyIdFromKeychain()
let clientDataHash: Data = sha256(serverChallenge)
let attestation = try await DCAppAttestService.shared.attestKey(
keyId: keyId,
clientDataHash: clientDataHash
)
// 把 attestation 发给服务器验证
关键点:
- 服务器必须控制 attestation 的发起,控制请求频率
- 失败时实现指数退避(exponential back-off),不要硬编码重试逻辑
- 在后台任务中执行,不要阻塞用户流程
- 验证必须由服务器完成,不要信任客户端的验证结果
Attestation 对象包含三部分:format(固定字符串标识 Apple 匿名证明)、attestation statement(证书链和 receipt)、authenticator data(App 和证明信息)。
证书链证明密钥在真实 Apple 硬件上生成,leaf certificate 包含 nonce、key ID、relying party identifier。macOS 27 还包含 ACL Blob OID,记录 Full Security 模式和 SIP 状态。
(10:28)iOS 27 的 authenticator data 末尾新增 extensions 结构,包含两个字段:
launch validation category:App Store、TestFlight 或其他bundle version:当前运行的 App 版本
服务器应监控这些字段的异常值,纳入风险评估。
生成 Assertion 保护通信
(12:33)Attestation 验证通过后,App 可以用同一个密钥生成 assertion,保护后续请求:
import DeviceCheck
let keyId: String = fetchKeyIdFromKeychain()
let clientDataHash: Data = sha256(serverChallenge)
let assertion = try await DCAppAttestService.shared.generateAssertion(
keyId: keyId,
clientDataHash: clientDataHash
)
// 把 assertion 嵌入请求 payload 发给服务器
关键点:
- Assertion 在设备本地生成,不经过 Apple 服务器,可以按需实时生成
- 涉及加密运算,有 CPU 开销,避免高频批量生成
- 服务器必须验证 assertion 中的 counter 严格递增,防止重放攻击
- 如果 counter 不变或下降,说明可能是被篡改的 App 副本
常见陷阱
(15:02)几个容易踩的坑:
用户重新安装 App 或恢复设备会导致 key rotation,不要直接拒绝新密钥。保留历史密钥记录,结合 Fraud Metric 判断是否为异常行为。
验证失败时不要直接阻断用户。先降级功能(限制提现额度、隐藏敏感数据),在加强监控的同时允许有限访问。
Fraud Metric
(16:35)Fraud Metric 检测 compromised 设备作为 broker 为其他设备签发 attestation 的攻击模式。服务器用 attestation 中的 receipt 向 Apple 的 App Attest data server 发起 POST 请求,获取 fraud metric。
返回的 receipt 包含签名、证书链和 payload,其中 risk metric 字段就是 fraud metric 计数。这个计数是近似值,表示过去 30 天内该设备上生成的唯一 attested key 数量。
receipt 有刷新窗口,由 not before 和 expiration time 字段控制。正常用户的 App 重装或设备恢复也会贡献到 fraud metric,所以不要直接用它阻断用户,而是作为调查信号,监控基线,识别异常峰值。
核心启发
给金融 App 加上交易签名
做什么:在转账、支付等关键操作前,用 App Attest assertion 对交易 payload 签名,服务器验证后才执行。
为什么值得做:即使攻击者拿到了用户密码,也无法用篡改的 App 发起有效交易请求。
怎么开始:在交易提交前调用 generateAssertion,把 assertion 和交易数据一起发给服务器,后端验证 assertion 的签名和 counter。
给游戏加上排行榜防作弊
做什么:玩家提交分数时附带 assertion,服务器验证 App 未被修改后才计入排行榜。 为什么值得做:防止攻击者注入作弊菜单后提交虚假高分。 怎么开始:在分数提交接口中要求 assertion,同时监控 launch validation category 和 bundle version,异常值直接拒绝。
用 Fraud Metric 识别设备农场
做什么:把 Fraud Metric 接入风控引擎,标记异常设备。 为什么值得做:设备农场里的每台设备都是真机,传统设备指纹拦不住,但 Fraud Metric 能暴露一台设备批量生成密钥的行为。 怎么开始:服务器定期刷新 receipt 获取 fraud metric,设置阈值告警,结合其他风控特征综合判断。
给 macOS App 加上完整性校验
做什么:macOS 27 首次支持 App Attest,利用 ACL Blob OID 验证设备是否开启了 Full Security 和 SIP。 为什么值得做:Mac 端的高价值业务(如企业软件、付费工具)以前缺乏可靠的防篡改手段。 怎么开始:解析 attestation 证书链中的 ACL Blob OID,检查 Full Security 和 SIP 状态,关闭 SIP 的设备标记为高风险。
用 isSupported 做第一道风控门槛
做什么:把 isSupported 的返回值纳入用户风险评估。
为什么值得做:越狱设备或篡改环境可能让 App Attest 不可用,这个信号本身就是异常指标。
怎么开始:记录每个用户的 isSupported 响应历史,突然出现大量 false 的设备重点监控。
关联 Session
- 101 Keynote — WWDC26 开场,概述 Apple 平台安全新方向
- 347 Security agentic — 安全领域的 Agentic 应用,与 App Attest 的风控思路互补
- 379 Trust Insights — 信任洞察相关 session,涉及安全评估和风险控制
- 205 App Store — App Store 分发和验证,与 launch validation category 相关
- 262 Swift — Swift 语言新特性,可能涉及安全相关的语言层面改进
评论
GitHub Issues · utterances