文章总结: 本文基于BlackHatUSA2026议题整理pass-the-passkey攻击家族,指出passkey虽优于密码但并非天然安全,攻击面覆盖RP、浏览器、OS、认证器与同步服务,包含断言重放、日志泄露、challenge注入等20多种技术。建议RP使用一次性服务器状态验证challenge,修复Windows事件日志泄露完整断言问题,并强调部署时需修复假设而非停止使用passkey。
综合评分: 88
文章分类: 漏洞分析,web安全,红队,安全工具
Black Hat USA 2026:Passkey传递攻击
原创
Max Luo
Max Luo
白帽子罗棋琛
2026年9月15日 08:18
广东
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
通行密钥也会被传递:Pass-the-Passkey 攻击面与防线
Black Hat USA 2026 议题笔记:Pass-the-Passkey Family of Attacks
Passkey 解决了密码体系里最难缠的几个问题:没有可钓鱼的共享秘密,私钥不发给服务器,凭据绑定 RP ID,认证结果还覆盖 challenge、origin、用户在场与用户验证状态。但“抗钓鱼”不是一句覆盖整个终端、浏览器、操作系统、密码管理器和云身份平台的魔法属性。只要周边实现泄露签名结果、允许 challenge 重放、错误处理同步私钥,或者让受控进程调用系统 WebAuthn API,攻击者未必需要导出私钥,也能把一次有效 assertion 传到自己的会话。
Michael Grafnetter 的公开课件与白皮书把这类路径归为 Pass-the-Passkey:3 个实现漏洞、20 多种攻击技术,覆盖 assertion 日志泄露、重放、relay、系统提示欺骗、WebAuthn API hook、同步 Passkey 导出、OIDC Token 兑换和 Shadow Passkey 持久化。
图 1:研究讨论的是围绕 Passkey 的完整攻击家族,不是单一协议缺陷
本文基于课件和白皮书整理,不提供 C2 命令、DLL 注入、Assertion 重放载荷或导出私钥样例。代码集中在 RP 验证、审计、检测和策略门禁。结论并不是停止部署 Passkey:公开材料同样强调,Passkey 仍显著优于密码;需要修复的是“只要启用 Passkey 就天然安全”的部署假设。
1、Passkey 抗钓鱼的前提,是四个绑定同时成立
WebAuthn 认证开始时,RP 生成随机 challenge;浏览器把 challenge、真实 origin 和操作类型写入 clientDataJSON;认证器对 authenticatorData || SHA-256(clientDataJSON) 签名。私钥留在 Windows Hello、硬件安全密钥或同步认证器中。
图 2:RP 提供 challenge,浏览器绑定 origin,认证器使用私钥签名,服务器用登记公钥验证
图 3:签名不仅证明拥有私钥,也应把凭据、RP、用户验证和本次事务绑定在一起
服务器最终要验证四类不变量:
text
事务绑定:challenge 是本会话生成、未过期、仅使用一次 来源绑定:origin、topOrigin/crossOrigin 与 RP 策略一致 凭据绑定:credentialId 属于预期用户,rpIdHash 匹配 RP ID 认证语义:签名有效,UP/UV、扩展和 signCount 满足策略
W3C WebAuthn Level 3 的 assertion verification 不是一句“验签成功”。规范要求验证 type=webauthn.get、challenge、origin、跨源状态、rpIdHash、UP/UV、签名和计数器等一整套条件。
图 4:Passkey 的安全属性由客户端、认证器和 RP 共同完成,任何一方省略检查都会削弱整体保证
因此,Passkey 不是可以转发的“新密码”;真正被攻击者传递的是签名 assertion、可导出的同步私钥、被替换的 challenge,或注册在受害账户上的新公钥。
2、攻击面横跨 RP、浏览器、OS、认证器与同步服务
一条认证链至少包含 RP 公钥数据库、HTTPS、浏览器、扩展、Windows WebAuthn API、密码管理器、CTAP2 传输和认证器安全单元。
图 5:最难攻破的往往是安全单元,研究中的多数路径选择了它周围的软件边界
课件把既有风险和新研究放在同一张图里:硬件侧信道、平台认证器漏洞、同步密钥泄露、恶意扩展、MITM 请求篡改,以及 Windows/Entra 实现问题。风险评估必须先标注攻击者所在层:
yaml
passkey_threat_model:relying_party:threats: [challenge_replay, weak_origin_check, counter_rollback, rogue_registration] browser:threats: [malicious_extension, injected_script, compromised_profile] operating_system:threats: [event_log_leak, api_hook, ui_spoofing, untrusted_process] authenticator:threats: [firmware_bug, side_channel, stolen_unlocked_device] sync_provider:threats: [vault_takeover, unsafe_export, recovery_flow_abuse] identity_plane:threats: [admin_preregistration_abuse, token_exchange, policy_bypass]
同一个“Passkey 登录成功”在不同层被破坏时,补救完全不同。RP 重放要修服务端状态;恶意扩展要做浏览器治理;同步密钥外泄要处置 Vault 与所有相关凭据;Shadow Passkey 则需要撤销账户上的恶意认证方法并调查 Graph/API 权限。
3、RP 验证要用一次性服务器状态,不要把 JWT 误当 nonce
研究发现,Entra ID 当时用短期签名 JWT 作为 challenge,减少服务器端存储,但未做到严格单次消费。课件用“JWT ≠ NONCE”概括问题:签名只能证明 challenge 由服务器签发,不能证明它没有被使用过。
图 6:可验证、未过期与未使用是三个不同属性,JWT 只天然解决前两项
安全实现应把 challenge 与会话、用户、操作和有效期一起存入服务器端一次性记录。认证请求进入后,在同一数据库事务中锁定记录,完成绑定与签名验证,再标记为已消费:
typescript
typeChallengeRecord = { digest: string; sessionId: string; userId: string; purpose: "webauthn.get"; expiresAt: number; consumedAt: number | null; }; asyncfunctionverifyAuthentication(tx: DbTransaction, assertion: AssertionInput, sessionId: string, userId: string, ): Promise<void> { const client = parseStrictClientDataJSON(assertion.clientDataJSON); const digest = sha256Base64Url(b64urlDecode(client.challenge)); const row = await tx.challenge.lockForUpdate(digest); if (!row || row.sessionId !== sessionId || row.userId !== userId) thrownewAuthError("challenge_binding_failed"); if (row.purpose !== "webauthn.get" || row.expiresAt < Date.now()) thrownewAuthError("challenge_expired"); if (row.consumedAt !== null) thrownewAuthError("challenge_replayed"); verifyBindings(assertion, row.expected); awaitverifySignature(assertion, row.registeredPublicKey); await tx.challenge.markConsumed(digest, Date.now()); }
必须在数据库事务里先锁住 challenge,再完成验证与消费,不能“无锁查询未使用—验签—最后更新”,否则并发请求会形成 TOCTOU。上例采用验证成功后消费;若业务要求 assertion 一经提交即作废,可以设计 pending → verifying → consumed/failed 状态机,但不能靠一次普通查询和一次普通更新拼接出单次语义。
接下来按规范验证客户端数据和认证器数据:
typescript
functionverifyBindings(input: AssertionInput, expected: Expected): void { const client = parseStrictClientDataJSON(input.clientDataJSON); if (client.type !== "webauthn.get") thrownewAuthError("wrong_type"); if (!timingSafeEqual(b64urlDecode(client.challenge), expected.challenge)) thrownewAuthError("wrong_challenge"); if (!expected.origins.has(client.origin)) thrownewAuthError("wrong_origin"); if (client.crossOrigin === true && !expected.allowCrossOrigin) thrownewAuthError("unexpected_cross_origin"); const auth = parseAuthenticatorData(input.authenticatorData); if (!timingSafeEqual(auth.rpIdHash, sha256(expected.rpId))) thrownewAuthError("wrong_rp_id"); if (!auth.flags.up) thrownewAuthError("user_presence_required"); if (expected.requireUv && !auth.flags.uv) thrownewAuthError("user_verification_required"); }
实际项目优先选择成熟 WebAuthn 库,再用 conformance/负向测试验证配置;不要把上面片段复制成自研完整实现。
4、CVE-2026-34348:事件日志不应保存可重放认证材料
白皮书披露,Windows 11 的 Microsoft-Windows-WebAuthN/Operational 日志曾写入完整 PublicKeyCredential assertion,包含 credential ID、authenticatorData、clientDataJSON、signature 与 userHandle。经过 Windows WebAuthn API 的 Windows Hello、硬件密钥、插件和混合认证都可能进入该日志;已认证低权限用户还可远程读取日志。
图 7:诊断日志保存完整 assertion,把一次认证结果变成了可采集的敏感材料
图 8:日志读取权限与远程 Event Log Reader 能力把本地信息泄露扩展到身份分离场景
这会破坏“高权限账号只在受控端点使用认证器”的边界:普通会话若能读取另一用户的完整 assertion,就不需要触碰硬件密钥或 TPM。研究把它与 Entra replay 组合,形成绕过 phishing-resistant MFA 的链。
微软于 2026 年 7 月 14 日发布更新。白皮书称,修复后的 Windows 将日志 assertion 的签名字段截断为 6 字节,保留排障价值但无法完成签名验证。生产验收应同时检查补丁版本和日志实际内容,不能只确认 KB 已安装。
powershell
$Log = 'Microsoft-Windows-WebAuthN/Operational'$Events = Get-WinEvent-FilterHashtable@{ LogName = $Log; Id = 2106 } -MaxEvents20foreach ($Eventin$Events) { $Xml = [xml]$Event.ToXml() $Value = ($Xml.Event.EventData.Data | Where-Object Name -eq'authenticationResponseJSON').'#text'if ([string]::IsNullOrWhiteSpace($Value)) { continue } $Json = $Value | ConvertFrom-Json [pscustomobject]@{ Time = $Event.TimeCreated Computer = $Event.MachineName SignatureLength = [string]$Json.response.signature.Length FullAssertionSuspected = ([string]$Json.response.signature.Length -gt16) } }
该脚本只输出长度,不导出 assertion 内容。若发现完整签名,按凭据泄露处理:隔离主机、修补系统、调查 Event Log Readers 和远程日志访问、撤销受影响账户的 Passkey,并检查相关云会话与 Token。
5、重放、截获和 challenge 注入,是三种不同故障模式
Pass-the-Passkey 不能笼统归为 replay。课件将 Detour 分成三种模式:
- Assertion Replay:受害者 assertion 同时被受害者和攻击者使用,依赖 RP 未阻止 challenge/计数器重放;
- Assertion Capture:hook 截获 assertion,不返回给浏览器,由攻击者先使用;即使服务器正确单次消费,受害者只看到短暂错误;
- Challenge Injection:攻击者先在自己会话创建 challenge,再让受害者认证器签名;它能针对已做 session binding 的 RP。
图 9:重放保护只覆盖第一列,端点被控后的实时截获与 challenge 注入需要端点侧防线
Entra 研究还发现 challenge 可在较长窗口被接受,且当时未普遍跟踪 signature counter。2026 年 5 月的部分修复开始对会递增 counter 的设备绑定 FIDO2 密钥做检查;Windows Hello 常返回 0,同步 Passkey 也可能不支持单调计数,因此 counter 不能替代 challenge 单次消费。
图 10:计数器可发现克隆或回滚,但只有认证器维护非零递增值时才有效
图 11:公开材料明确把它称为 partial fix;不同认证器类型仍需分别验证
服务端应按凭据记录维护 signCount,并把异常作为风险信号而非简单自动接受:
python
defevaluate_counter(stored: int, observed: int, backup_eligible: bool) -> str: if stored == 0and observed == 0: return"unsupported"if observed > stored: return"advance"if backup_eligible: return"rollback_requires_risk_review"return"possible_clone_or_replay"
同步凭据可能在设备迁移时发生 counter 回退,不能用硬件密钥策略机械套用。高价值账号应优先设备绑定认证器并启用 attestation,从根本上缩小这种例外。
6、端点失陷后,攻击者可以借用认证器,而不必导出私钥
Windows 浏览器把 WebAuthn 请求交给 webauthn.dll,系统再显示 Credential UI 并路由到 Windows Hello、FIDO2 密钥、手机或第三方插件。任何 Windows 应用都能调用 Win32 WebAuthn API;浏览器负责从页面真实地址填 origin,而本地恶意进程直接调用 API 时可以提供它希望用户签名的 RP/origin 上下文。
研究据此展示了提示钓鱼、Prompt Flooding、RDP/Hyper-V 远程提示、窗口句柄/应用标识欺骗,以及浏览器内 WebAuthn API hook。用户看到的是熟悉的系统 Passkey 窗口,未必能判断是哪一个进程发起。
图 12:反复出现的系统认证提示会制造“点一下让它消失”的疲劳确认
图 13:系统提示中的应用名称和图标若可受调用者元数据影响,就不能独立证明请求来源
图 14:端点侧代码可以篡改 RP、challenge、UP/UV 等请求参数,RP 必须独立验证最终 assertion 的每一项语义
端点侧需要同时限制代码执行、扩展安装、进程注入和远程会话设备重定向。对高权限身份,Passkey ceremony 只允许在 PAW/SAW 上发生,并把非浏览器 WebAuthn 调用视为高风险事件。
yaml
privileged_passkey_endpoint_policy:allowed_callers:-signed_browser_stable_channel-approved_os_signin_componentsdeny:-unsigned_webauthn_clients-user_installed_browser_extensions-webauthn_redirection_over_untrusted_rdp-passkey_use_from_general_purpose_vdirequire:-application_control-code_integrity-edr_injection_telemetry-browser_extension_allowlist-device_compliance
用户培训不能只说“看到 Windows Hello 就确认”。提示必须与用户刚刚发起的业务动作、浏览器域名和设备上下文对应;任何意外 prompt 都应拒绝并上报。
7、同步 Passkey 的风险来自“可迁移”,也是它的产品价值
设备绑定 Passkey 留在单一 TPM 或硬件密钥;同步 Passkey 需要跨手机、电脑和云 Vault 复制私钥。后者极大改善恢复与多设备体验,但密码管理器账户、同步服务、客户端缓存和导出文件都进入信任边界。
图 15:同步凭据强调可用性,设备绑定凭据强调私钥不离开单一认证器
图 16:云端可用 HSM 与机密计算加固同步链,但客户端仍必须接触可用私钥材料
白皮书列出 KeePassXC、Bitwarden 和 Credential Exchange Format(CXF)等导出路径。风险不在“存在标准”本身,而在导出容器是否加密、口令强度、文件落盘位置、备份/同步软件是否再次复制,以及导出后能否被发现和撤销。
图 17:可互操作凭据格式让迁移成为正式能力,也要求传输编排器承担机密性与完整性保护
企业策略应按身份价值分层:
yaml
passkey_tiers:workforce_standard:synced_allowed:truevault_requirements: [mfa, device_encryption, managed_client] privileged_admin:synced_allowed:falsedevice_bound_required:trueattestation_required:trueapproved_aaguids: [organization-reviewed-models] break_glass:authenticators:2storage:separate_physical_custodycloud_sync:forbiddenquarterly_test:required
EDR/DLP 应检测 .passkey、密码管理器 JSON 和 CXF 导出在下载、桌面、临时目录、邮件和云盘中的出现,但不要收集文件内容到集中日志;文件名、哈希、路径、创建进程和分类结果已经足够触发调查。
8、Shadow Passkey 与 OIDC Token 兑换把认证变成持久化入口
很多身份平台允许管理员为其他用户预注册 Passkey,便于远程入职时发放已绑定硬件密钥。同一个 API 权限也能被攻击者用于给高价值账户注册额外认证器。密码重置不会删除这把独立公钥,恶意 Passkey 会一直有效,直到被发现并移除。
图 18:恶意注册的 Passkey 是独立认证因素,传统“改密码清会话”不一定清除它
白皮书指出,Entra 管理注册涉及 UserAuthenticationMethod.ReadWrite.All 或 UserAuthMethod-Passkey.ReadWrite.All,Okta 对应 okta.users.manage。这些权限应按 Tier-0 应用权限管理,采用短期授权、审批和独立告警。
kusto
AuditLogs | where Category =~ "UserManagement" | where OperationName has_any ("passkey", "FIDO", "authentication method") | mv-expand TargetResources | extend TargetUPN = tostring(TargetResources.userPrincipalName) | project TimeGenerated, OperationName, Result, InitiatedBy, TargetUPN, CorrelationId | order by TimeGenerated desc
Passkey assertion 还可能进入 OIDC Authorization Code 流程,换取 access、refresh 和 ID token。处置事件时不能止于删除 Passkey:必须撤销相关刷新令牌、会话、设备注册和应用授权,并检查新建 Service Principal/Consent。
图 19:认证 assertion 是入口,后续 Token 才是访问 Microsoft Graph、邮件和云资源的实际载体
9、检测要关联“谁调用 WebAuthn、谁读日志、谁改认证方法”
白皮书给出的端点信号很具体:非浏览器进程调用 WebAuthn API、进程读取 WebAuthN Operational 日志、枚举窗口句柄、向浏览器注入、异常 named pipe、webauthn.dll 入口被 hook,以及 LoadLibraryW/LoadLibraryExW 周围完整性变化。
yaml
title:非浏览器进程调用WindowsWebAuthnAssertionAPIstatus:experimentallogsource:category:api_callproduct:windowsdetection:selection:ApiName:WebAuthNAuthenticatorGetAssertionfilter_approved:ProcessImage|endswith:-'\\msedge.exe'-'\\chrome.exe'-'\\firefox.exe'-'\\CredentialUIBroker.exe'condition:selectionandnotfilter_approvedfalsepositives:-经批准的身份测试、VPN或企业登录客户端level:high
如果 EDR 没有 API telemetry,可关联模块加载、Operational 事件中的 ProcessID 和进程签名。检测逻辑不应依赖公开 PoC 的默认 pipe 名,因为参数可以修改。
yaml
correlation:suspicious_passkey_ceremonywindow:10mgroup_by: [host, user_sid] require_any_two:-nonbrowser_webauthn_call-webauthn_log_read_by_unapproved_process-browser_remote_thread_or_module_tamper-unexpected_passkey_prompt_report-passkey_registration_for_privileged_user-new_oidc_refresh_token_from_new_deviceresponse:-isolate_endpoint-revoke_sessions_and_refresh_tokens-inventory_and_remove_unapproved_passkeys-preserve_webauthn_and_process_telemetry_without_assertion_secret
RP 日志应记录 challenge ID 的哈希、session ID、credential ID 哈希、AAGUID、UP/UV/BE/BS、counter 结果、origin、设备与风险决策;绝不能记录完整 signature、完整 clientDataJSON 或任何可复用 assertion。clientDataJSON 本身不是私钥,但和签名、认证器数据组合后属于可重放认证材料,没有必要进入通用日志管道。
10、部署 Passkey 的正确结论是分层加固,而不是回到密码
课件最后的判断很克制:Passkey 仍值得采用,因为这些攻击总体比密码窃取更难;端点失陷和实现漏洞可以绕过 phishing-resistant MFA;组织必须主动测试 replay、relay 和 tampering。
图 20:大部分新技术集中在操作系统与应用接口层,而不是直接击破认证器私钥
图 21:攻击面可连接端点调用、assertion 处理、RP 会话与云 Token,因此防守也必须跨层关联
图 22:继续部署、承认端点边界、测试实现,是比“Passkey 安全/不安全”二元判断更准确的结论
上线验收可以压缩成以下门禁:
yaml
passkey_release_gate:relying_party:challenge_random:passchallenge_single_use_atomic:passchallenge_session_bound:passexact_origin_allowlist:passrp_id_hash_verified:passup_uv_policy_verified:passsignature_verified:passcounter_policy_by_authenticator_class:passendpoint:windows_cve_2026_34348_patched:passfull_assertion_absent_from_logs:passbrowser_extensions_allowlisted:passnonbrowser_webauthn_detected:passidentity:admin_registration_permissions_jit:passpasskey_registration_alerted:passtoken_revocation_runbook_tested:passprivileged_users:device_bound_only:passattestation_enforced:passmanaged_workstation_only:pass
Passkey 的价值来自把认证从“知道一个秘密”改成“在正确 RP、正确事务和正确设备上下文中证明私钥控制”。Pass-the-Passkey 研究提醒我们,后半句话不能省略。只检查签名,相当于只验证钥匙是真的,却没有验证它是否用于这扇门、这一次开门、这个会话和这名用户。
真正稳健的部署不是把“phishing-resistant”当最终结果,而是持续证明:服务器不接受旧 challenge,端点不会泄露 assertion,高权限账号不用可导出的同步凭据,异常注册会被发现,认证后产生的 Token 也能被快速撤销。
资料来源
- Black Hat 官方 Session 页面
- Black Hat USA 2026 Session 页面
- W3C WebAuthn Level 3
- Microsoft MSRC:CVE-2026-34348
- FIDO Alliance:Credential Exchange Format
原始会议材料(仓库内)
- 演讲课件 PDF
- 配套白皮书 PDF
开源资料与原始议题 PDF
本文对应的 Markdown 原稿、Black Hat 原始议题 PDF 与配图已整理到 GitHub,可按文章编号查找和下载。
https://github.com/cybermaxluo/black-hat-usa-2026-talks
也可以点击文末“阅读原文”进入仓库。欢迎 Star、提交 Issue 或参与勘误。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:白帽子罗棋琛 Max Luo
Max Luo《Black Hat USA 2026:Passkey传递攻击》