ARTICLE / 安全

Passkey与无密码认证安全取证深度分析

无密码认证(Passwordless Authentication)正在迅速重塑互联网身份验证的基本范式。FIDO Alliance 的统计数据表明,截至2025年底,全球已有超过30亿台设备支持FIDO2标准,Google、Apple和Microsoft三大平台均已将Passkey作为默认推荐的认证方式。Passkey通过公私钥对替代传统密码,结合设备本地生物识别或PIN码完成认证,从根本上消除了密码泄露、钓鱼攻击和凭据填充等传统认证威胁。

然而,Passkey并非万无一失的安全银弹。攻击面已从密码存储和传输环节转移到设备端密钥管理、跨设备同步链安全、近场通信中继攻击、以及RP(Relying Party)端的WebAuthn实现缺陷等全新领域。2024年以来,针对Passkey的BLE/NFC中继攻击、通过iCloud Keychain同步链注入恶意设备、利用浏览器扩展拦截WebAuthn API调用等攻击手法已相继被安全研究者公开披露。这些新型攻击模式要求蓝队取证分析人员建立全新的分析方法论:从CTAP2二进制协议的解码到Secure Enclave密钥生命周期的追踪,从WebAuthn Challenge-Response时序分析到跨设备同步链完整性的验证。

本文从蓝队取证实战视角出发,系统性地覆盖Passkey与FIDO2无密码认证体系的全链路安全分析——从WebAuthn协议栈的安全审计到CTAP2通信链路的取证分析,从密钥存储硬件安全模块的取证到BLE/NFC中继攻击的检测,从设备同步链完整性的验证到认证日志的重建与异常行为检测,结合Apple/Google/Microsoft三大平台Passkey实现差异与真实安全事件还原完整的取证链。


0x01 技术基础与取证概述

认证技术演进历程

从密码到Passkey,认证技术经历了四个主要阶段的演进。每个阶段在解决前一阶段核心威胁的同时,也引入了新的攻击面和取证挑战。

认证阶段核心机制主要威胁取证关注点时间范围
密码认证用户名+密码撞库、钓鱼、暴力破解密码存储、传输加密、登录日志1960s-2010s
MFA多因素认证密码+OTP/SMS/硬件令牌SIM Swapping、实时钓鱼代理、MFA疲劳攻击OTP日志、设备绑定、推送审批记录2010s-2020s
无密码认证(FIDO2)公私钥对+设备本地验证设备丢失、平台认证器绕过密钥注册链、设备信任锚、认证日志2020s-
Passkey同步密钥同步的平台认证器密钥对同步链注入、中继攻击、云端密钥泄露同步链验证、设备链完整性、跨平台同步日志2022-

FIDO2协议栈架构

FIDO2协议栈由两大核心组件构成:W3C WebAuthn(Web Authentication API)和FIDO Alliance CTAP2(Client to Authenticator Protocol)。WebAuthn定义了浏览器与RP服务器之间的认证接口规范,CTAP2定义了客户端(通常是浏览器或操作系统)与认证器(Authenticator)之间的通信协议。

协议层标准规范职责范围通信边界
WebAuthn APIW3C WebAuthn Level 3浏览器JS API与RP Server交互Browser ↔ RP Server(HTTPS)
CTAP2FIDO Alliance CTAP 2.2客户端与认证器通信Client ↔ Authenticator(USB/BLE/NFC)
CBOR/COSERFC 8949 / RFC 8152二进制编码与密码学算法数据序列化层
FIDO ServerFIDO Alliance Server SpecRP端注册与认证验证逻辑Server ↔ RP Database

Passkey vs FIDO2 Security Key vs Resident Key

Passkey是FIDO2 Resident Key(也称为Discoverable Credential)的一种实现形态,但三者之间存在重要区别。理解这些区别对于正确分析取证数据至关重要。

特性FIDO2 Security KeyResident KeyPasskey
硬件形态独立USB/BLE/NFC设备认证器内部存储设备平台认证器或密码管理器
密钥存储Security Key安全芯片任何支持的认证器Secure Enclave / TPM / StrongBox
跨设备同步不支持取决于认证器实现支持(通过iCloud/Google/第三方)
Discoverable部分支持支持完全支持
用户验证Security Key上的按钮/PIN认证器自身的UV方式设备生物识别/PIN
RP指定Authenticator政策可指定政策可指定通常不限制
典型用途高安全场景企业SSO消费者日常认证
取证复杂度低(物理设备)高(涉及云同步链)

Platform Authenticator vs Roaming Authenticator

WebAuthn协议将认证器分为两大类:Platform Authenticator(平台认证器,与宿主设备物理绑定)和Roaming Authenticator(漫游认证器,可跨设备使用)。两者在取证分析中需要关注的数据源截然不同。

维度Platform AuthenticatorRoaming Authenticator
物理绑定绑定宿主设备可在多台设备间移动
通信方式本地API调用(无外部通信)USB HID / BLE / NFC
典型实现Touch ID / Face ID / Windows Hello / Android BiometricYubiKey / Feitian / Google Titan
userVerification通常为 internal通常为 preferred 或 required
取证数据源操作系统本地日志USB/BLE/NFC流量 + 操作系统日志
attestationplatform attestationindirect 或 direct attestation
攻击面操作系统层面通信链路 + 操作系统层面

FIDO2注册与认证流程

理解FIDO2的注册(Registration)和认证(Authentication)流程是取证分析的基础。以下ASCII流程图展示了完整的注册过程(navigator.credentials.create)。

┌──────────┐         ┌──────────────┐         ┌──────────────┐         ┌──────────────┐
│  Browser  │         │   RP Server  │         │ Client/Auth  │         │ Authenticator│
│  (WebAuthn)│         │  (WebAuthn)  │         │   (CTAP2)    │         │  (HW/SW)     │
└─────┬────┘         └──────┬───────┘         └──────┬───────┘         └──────┬───────┘
      │                      │                        │                        │
      │  navigator.credentials.create(options)         │                        │
      │─────────────────────>│                        │                        │
      │                      │                        │                        │
      │  Challenge + RP ID   │                        │                        │
      │  + User Info         │                        │                        │
      │<─────────────────────│                        │                        │
      │                      │                        │                        │
      │  CTAP2 MakeCredential│                        │                        │
      │  (CBOR)              │                        │                        │
      │──────────────────────────────────────────────>│                        │
      │                      │                        │  User Verification     │
      │                      │                        │  (生物识别/PIN)        │
      │                      │                        │───────────────────────>│
      │                      │                        │                        │
      │                      │                        │  密钥对生成             │
      │                      │                        │  (私钥存储于Auth)      │
      │                      │                        │<───────────────────────│
      │                      │                        │                        │
      │                      │  Attestation Object   │                        │
      │                      │  (authData + attStmt) │                        │
      │                      │<──────────────────────│                        │
      │  Attestation Object  │                        │                        │
      │<─────────────────────│                        │                        │
      │                      │                        │                        │
      │                      │  验证 Attestation      │                        │
      │                      │  存储 Credential ID   │                        │
      │                      │  + Public Key          │                        │
      │  注册成功             │                        │                        │
      │─────────────────────>│                        │                        │

认证过程(navigator.credentials.get)的流程如下:

┌──────────┐         ┌──────────────┐         ┌──────────────┐         ┌──────────────┐
│  Browser  │         │   RP Server  │         │ Client/Auth  │         │ Authenticator│
│  (WebAuthn)│         │  (WebAuthn)  │         │   (CTAP2)    │         │  (HW/SW)     │
└─────┬────┘         └──────┬───────┘         └──────┬───────┘         └──────┬───────┘
      │                      │                        │                        │
      │ navigator.credentials.get(options)            │                        │
      │─────────────────────>│                        │                        │
      │                      │                        │                        │
      │  Challenge           │                        │                        │
      │  + allowedCredentials│                        │                        │
      │<─────────────────────│                        │                        │
      │                      │                        │                        │
      │  CTAP2 GetAssertion  │                        │                        │
      │  (CBOR)              │                        │                        │
      │──────────────────────────────────────────────>│                        │
      │                      │                        │  User Verification     │
      │                      │                        │───────────────────────>│
      │                      │                        │                        │
      │                      │                        │  签名 Challenge        │
      │                      │                        │  (使用私钥)            │
      │                      │                        │<───────────────────────│
      │                      │                        │                        │
      │                      │  Assertion             │                        │
      │                      │  (authData + sign)     │                        │
      │                      │<──────────────────────│                        │
      │  Assertion           │                        │                        │
      │<─────────────────────│                        │                        │
      │                      │                        │                        │
      │                      │  验证签名              │                        │
      │                      │  比对 Sign Counter     │                        │
      │  认证成功             │                        │                        │
      │─────────────────────>│                        │                        │

取证工具链

Passkey安全事件取证需要一套覆盖协议分析、密钥审计、日志聚合和流量捕获的专用工具链。

工具名称功能定位适用场景安装方式
Wireshark网络包分析CTAP2 BLE/USB流量解码brew install wireshark
fido2-toolsFIDO2命令行工具Security Key管理与测试brew install libfido2
py_webauthnWebAuthn Python库RP端认证逻辑测试与验证pip install py-webauthn
libfido2FIDO2 C语言库FIDO2协议分析与fuzzingbrew install libfido2
coseCOSE编码解码库CBOR/COSE数据结构解析pip install cose
CBORDiagCBOR诊断工具CBOR数据包分析pip install cbor-diag
AuthenticatorInfo认证器信息查询认证器元数据和功能分析fido2-token -L
Chrome DevTools浏览器调试工具WebAuthn API调用监控内置Chrome
macOS Unified Log系统日志Apple Passkey事件分析log stream –predicate
Windows Event Viewer事件查看器Windows Hello事件分析内置Windows
logcatAndroid日志Android Passkey事件分析Android SDK Platform Tools
mitmproxyHTTPS中间人代理RP通信流量拦截pip install mitmproxy

0x02 WebAuthn协议栈安全审计

WebAuthn API 深度解析

WebAuthn API是浏览器暴露给Web应用的JavaScript接口,包含两个核心方法:navigator.credentials.create()(注册)和navigator.credentials.get()(认证)。对这两个API的调用参数和返回值的正确性验证是RP端安全审计的关键。

注册请求参数结构:

const publicKeyCredentialCreationOptions = {
    challenge: Uint8Array.from(allowedCredentials, c => c),
    rp: {
        name: "Example Relying Party",
        id: "example.com"
    },
    user: {
        id: Uint8Array.from("user-id-bytes", c => c),
        name: "user@example.com",
        displayName: "Example User"
    },
    pubKeyCredParams: [
        { alg: -7, type: "public-key" },
        { alg: -257, type: "public-key" }
    ],
    authenticatorSelection: {
        authenticatorAttachment: "platform",
        userVerification: "required",
        residentKey: "required"
    },
    timeout: 60000,
    attestation: "direct"
};

认证请求参数结构:

const publicKeyCredentialRequestOptions = {
    challenge: Uint8Array.from(allowedCredentials, c => c),
    timeout: 60000,
    rpId: "example.com",
    allowCredentials: [
        {
            id: Uint8Array.from("credential-id", c => c),
            type: "public-key",
            transports: ["internal", "ble", "nfc", "usb"]
        }
    ],
    userVerification: "required"
};

RP服务端验证逻辑审计

RP服务器端的验证逻辑是Passkey安全的关键环节。验证不当将导致认证绕过或凭据伪造。RP端需要验证的核心要素包括:

验证环节验证内容常见漏洞安全影响
Challenge验证challenge与会话中存储的一致性未绑定会话、可重用challengeMITRE ATT&CK T1557
Origin验证response.origin与预期域名匹配未验证origin或子域名匹配过宽MITRE ATT&CK T1566
RP ID验证responserpId与预期一致RP ID匹配逻辑缺陷认证绕过
Signature验证使用存储的公钥验证签名未验证或使用不可信公钥签名伪造绕过
Sign Counter签名计数器单调递增未检查计数器克隆检测失效
Attestation验证Attestation Object有效性跳过attestation验证伪造认证器注册
User PresenceUserVerification标志匹配未检查UV标志降级攻击

Challenge-Response安全分析

Challenge-Response机制是WebAuthn安全性的核心。Challenge必须满足以下安全属性,任何违反都应视为取证关注点。

安全属性要求取证检查方法违规后果
随机性使用密码学安全随机数生成器检查RP源码中challenge生成逻辑可预测的challenge
唯一性每次注册/认证使用唯一challenge检查日志中challenge重复使用Challenge重放
绑定性Challenge绑定到用户会话和RP ID检查会话cookie与challenge的关联跨会话攻击
时效性Challenge在合理时间内过期检查timeout值与实际验证时间差延迟攻击
长度至少16字节(128位)解析认证日志中的challenge长度穷举攻击

Attestation Statement验证

Attestation Object包含认证器生成的attestation statement,用于证明注册请求确实来自合法的认证器。RP可以选择验证或跳过attestation,但从取证角度看,attestation提供了关键的认证器身份信息。

Attestation Format认证器类型信任锚取证价值
packedFIDO2 Security Key认证器制造商证书高:可追溯到具体硬件
tpmtTPM-based (Windows Hello)TPM制造商证书高:可关联TPM硬件
android-keyAndroid KeystoreGoogle设备认证证书中:可关联设备型号
android-safetynetAndroid SafetyNetGoogle服务端验证中:需要Google API验证
appleApple平台认证器Apple根证书高:可追溯Apple设备
none无attestationN/A低:无法验证认证器来源

常见WebAuthn实现漏洞

WebAuthn的RP端实现不当是Passkey安全事件中最常见的攻击入口。以下汇总了近年公开披露的典型漏洞类型。

漏洞类型漏洞描述MITRE ATT&CK危害等级
Challenge重用同一challenge用于多次认证T1557 Man-in-the-Middle
Origin验证缺失未验证浏览器发送的origin字段T1566 Phishing严重
RP ID匹配过宽使用后缀匹配而非精确匹配T1566 Phishing
公钥未绑定用户Credential ID与用户ID之间无绑定检查T1078 Valid Accounts
签名计数器不检查未验证signCount单调递增T1557.001 LLMNR/NBT-NS
Attestation绕过未验证attestation statementT1199 Trusted Relationship
UV标志降级未强制检查userVerification标志T1562 Impair Defenses
超时未设置Challenge无过期时间T1557.002 ARP Cache Poisoning

0x03 CTAP2通信链路安全取证

CTAP2协议概述

CTAP2(Client to Authenticator Protocol 2.2)定义了客户端(浏览器/操作系统)与认证器之间的通信协议。CTAP2消息使用CBOR(Concise Binary Object Representation)编码,支持四种传输层:USB HID、BLE(Bluetooth Low Energy)、NFC和Thunderbolt。不同传输层的安全特性和取证方法存在显著差异。

传输层带宽延迟安全特性距离限制取证可行性
USB HID高(64KB/s)极低(<1ms)物理连接,无无线嗅探有线连接高(USB监控)
BLE中(125KB/s)中(10-50ms)AES-CCM加密,ECDH密钥交换~10m中(BLE嗅探)
NFC低(424Kbit/s)低(<100ms)无额外加密(依赖CTAP2层)~4cm低(NFC嗅探困难)
Thunderbolt极高(40GB/s)极低物理连接,高带宽有线连接低(工具不成熟)

CTAP2 over USB/HID协议分析

USB HID是CTAP2最常用的传输方式。每个CTAP2消息封装在64字节的HID报告中,使用特定的消息分片机制处理超过单帧大小的CBOR数据。

USB HID CTAP2帧结构:

字节偏移长度字段名描述
0-34 bytesChannel ID通道标识符(0xFFFFFFFF为广播通道)
41 byteCMD/BUS命令字节(高4位)+ 数据包类型(低4位)
5-62 bytesPayload Length有效载荷长度(大端序)
7-6357 bytesPayload DataCBOR编码的命令/响应数据
fido2-token -L
fido2-token -I /dev/hidraw0
fido2-cred -t create -i /dev/hidraw0 -g -o cred.blob
import struct

def parse_ctap2_usb_hid_frame(raw_data):
    if len(raw_data) < 7:
        return None
    channel_id = struct.unpack(">I", raw_data[0:4])[0]
    cmd_byte = raw_data[4]
    cmd_type = (cmd_byte >> 4) & 0x0F
    init_packet = (cmd_byte & 0x01) == 0
    payload_len = struct.unpack(">H", raw_data[5:7])[0] if init_packet else 0
    payload = raw_data[7:64] if init_packet else raw_data[5:64]
    return {
        "channel_id": f"0x{channel_id:08X}",
        "cmd_type": cmd_type,
        "is_init_packet": init_packet,
        "payload_len": payload_len,
        "payload_hex": payload.hex()
    }
CTAP2 USB HID命令命令码功能取证价值
MSG0x10CTAP2 CBOR消息高:包含MakeCredential/GetAssertion
INIT0x86通道初始化中:通道建立痕迹
CBOR0x10CBOR编码消息高:同MSG
PING0x81连通性测试低:设备存在确认
CANCEL0x11取消操作低:用户交互取消
ERROR0xBF错误响应中:错误模式分析
KEEPALIVE0x82保持活跃低:操作进行中提示

CTAP2 over BLE传输安全

BLE传输是Passkey中继攻击(MITRE ATT&CK T1557)的主要攻击面。CTAP2 over BLE在CTAP2消息层之上增加了BLE会话加密层,但初始配对过程仍可能存在安全风险。

BLE传输的加密层级:

层级加密机制密钥交换安全特性
BLE Link LayerAES-CCM(BLE 4.2+)LE Secure Connections链路层加密
CTAP2 SessionAES-CCMECDH P-256会话层加密
CTAP2 Message无额外加密N/A(依赖会话层)

BLE传输取证要点:

sudo btmon -w ctap2_ble_capture.log
sudo hcidump -w ctap2_hci_capture.log
BLE取证环节数据采集方法取证信息分析工具
配对过程BLE嗅探器(Ubertooth)配对请求/响应、IO能力Wireshark + BLE插件
GATT服务发现BLE扫描认证器服务UUIDnRF Connect / GATTacker
CTAP2消息交互BLE嗅探CBOR编码的认证消息自定义解析脚本
信号强度(RSSI)BLE监听物理距离估计自定义RSSI分析
连接事件间隔BLE监听连接模式特征自定义时序分析

CTAP2 over NFC传输安全

NFC传输的物理距离限制(~4cm)使其在理论上是最安全的传输方式,但也面临NFC中继攻击(MITRE ATT&CK T1557.006)的威胁。NFC传输没有额外的加密层,所有安全性依赖CTAP2消息层自身的保护。

NFC安全特性描述取证意义
物理距离限制~4cm通信距离NFC relay攻击需要专用设备
无链路加密依赖CTAP2层保护NFC嗅探可获取完整CTAP2消息
传输速率低212/424 Kbit/s长消息传输可见
NFC论坛协议ISO 14443 / ISO 18092协议指纹可识别认证器类型

CBOR/COSE编码安全

CTAP2消息使用CBOR编码,密码学操作使用COSE(CBOR Object Signing and Encryption)算法。取证分析中需要解码CBOR数据包以提取认证器返回的关键信息。

COSE算法标识:

COSE算法ID算法名称适用场景安全强度
-7ES256(ECDSA P-256 SHA-256)FIDO2首选算法128位安全
-257RS256(RSASSA-PKCS1-v1_5 SHA-256)RSA认证器128位安全
-35ES384(ECDSA P-384 SHA-384)高安全需求192位安全
-37PS256(RSASSA-PSS SHA-256)RSA-PSS128位安全
-39EdDSAEd25519曲线128位安全
import cbor2
import json

def decode_ctap2_cbor_response(raw_bytes):
    try:
        decoded = cbor2.loads(raw_bytes)
        status_code = decoded.get(1, "unknown")
        response_data = {}
        if 2 in decoded:
            rp_id_hash = decoded[2].hex()
            response_data["rp_id_hash"] = rp_id_hash
        if 3 in decoded:
            flags = decoded[3]
            response_data["flags"] = {
                "UP": bool(flags & 0x01),
                "UV": bool(flags & 0x04),
                "AT": bool(flags & 0x40),
                "ED": bool(flags & 0x80)
            }
        if 4 in decoded:
            response_data["sign_count"] = decoded[4]
        if 5 in decoded:
            response_data["credential_id"] = decoded[5].hex()
        if 6 in decoded:
            response_data["public_key"] = decoded[6]
        return {"status": status_code, "data": response_data}
    except Exception as e:
        return {"error": str(e)}

CTAP2 PIN/UV认证协议

CTAP2定义了两个安全协议用于保护敏感操作:PIN协议(用于验证用户PIN码)和User Verification(UV)协议。这两个协议使用AES-CTR加密和HMAC-SHA256进行消息完整性保护。

安全协议版本加密算法MAC算法用途
PIN Protocol 1v1AES-CTRHMAC-SHA256PIN验证(已废弃)
PIN Protocol 2v2AES-CTRHMAC-SHA256PIN验证+权限管理
UV Protocolv1AES-CTRHMAC-SHA256生物识别验证

0x04 密钥存储安全取证分析

Apple Secure Enclave密钥存储架构

Secure Enclave是Apple设备中的独立安全协处理器,负责密钥生成、存储和密码学运算。在Passkey场景中,私钥始终生成并存储于Secure Enclave中,即使操作系统被root,也无法直接提取私钥。

Secure Enclave安全特性描述取证影响
硬件隔离独立处理器,独立内存无法通过内存转储获取密钥
密钥派生每个密钥从硬件UID派生密钥与特定硬件绑定
Access ControlSecure Enclave策略保护密钥访问需要用户认证才能使用密钥
不可导出私钥无法离开Secure Enclave传统取证方法无法提取私钥
计数器保护单调递增计数器可检测密钥克隆
防重放每次签名包含唯一nonce签名不可重放

macOS上Passkey取证数据源:

log stream --predicate 'subsystem == "com.apple.Accessibility"' --info
log stream --predicate 'process == "securityd"' --info
log stream --predicate 'eventMessage CONTAINS "passkey" OR eventMessage CONTAINS "WebAuthn"' --info
log show --predicate 'subsystem == "com.apple.cryptex"' --last 1h
macOS日志子系统相关事件取证信息
com.apple.Accessibility生物识别验证Face ID/Touch ID使用记录
securityd密钥操作密钥创建、签名、删除事件
com.apple.cryptex密钥同步iCloud Keychain同步事件
com.apple.fidoFIDO2协议WebAuthn操作日志
com.apple.passkeydPasskey管理Passkey注册、使用、删除事件

TPM 2.0密钥证明与Windows Hello

Windows平台使用TPM 2.0(Trusted Platform Module)作为Passkey的密钥存储后端。TPM提供硬件级的密钥生成和存储,同时支持远程证明(Remote Attestation)以验证密钥的硬件来源。

Get-Tpm | Select-Object TpmPresent, TpmReady, ManufacturerId
Get-CimInstance -Namespace root\cimv2\Security\MicrosoftTpm -ClassName Win32_Tpm | Select-Object *
TPM密钥层级密钥类型存储位置取证提取可能性
EK(Endorsement Key)RSA/ECCTPM内部不可提取(硬件根信任)
AK(Attestation Key)RSA/ECCTPM内部不可提取(用于证明)
SRK(Storage Root Key)RSA/ECCTPM内部不可提取(密钥层次根)
用户密钥(Passkey私钥)ECC P-256TPM加密存储不可直接提取(可通过TPM操作)

Windows Event Log取证:

Get-WinEvent -LogName "Microsoft-Windows-Hello-FIDO/Operational" -MaxEvents 100 |
    Format-Table TimeCreated, Id, Message -Wrap

Get-WinEvent -FilterHashtable @{
    LogName = 'Microsoft-Windows-Hello-FIDO/Operational'
    Id = 300, 301, 302, 400, 401, 402
} -MaxEvents 200
Windows Event ID事件描述取证价值
300WebAuthn注册开始事件起始点
301WebAuthn注册完成注册结果和认证器信息
302WebAuthn注册失败失败原因分析
400WebAuthn认证开始认证事件起始点
401WebAuthn认证完成认证结果和断言信息
402WebAuthn认证失败认证失败原因分析
1000Windows Hello凭据注册平台认证器注册
1001Windows Hello凭据使用平台认证器使用

Android Keystore/StrongBox实现

Android平台提供两级密钥存储后端:Keystore(基于TEE,Trusted Execution Environment)和StrongBox(基于专用安全芯片,如Google Titan M或硬件安全模块)。从Android 9开始,StrongBox被要求支持FIDO2 Authenticator功能。

存储后端硬件基础安全等级取证提取难度典型设备
Android Keystore (TEE)ARM TrustZone大多数Android设备
StrongBox (SE)专用安全芯片极高极高Pixel 3+、Samsung S10+
ARM CryptoCellARM TrustZone+中高部分ARM设备

Android Passkey取证数据源:

adb logcat -s Fido2Manager:V WebAuthnManager:V BiometricPrompt:V
adb logcat -b events | grep -E "passkey|fido|webauthn"
adb shell dumpsys credential_manager
adb shell settings get secure enabled_accessibility_services

密钥备份与同步机制

Passkey的核心优势之一是支持跨设备同步。但同步机制本身也引入了新的攻击面和取证挑战。不同平台的同步实现差异显著,对取证方法论提出了差异化要求。

同步平台同步服务加密方式密钥托管攻击面
AppleiCloud KeychainE2EE + iCloud Advanced Data ProtectioniCloud密钥链同步iCloud账号接管、同步链注入
GoogleGoogle Password ManagerE2EE(默认开启)Google账号密钥Google账号接管、同步链注入
MicrosoftWindows HelloMicrosoft Account + TPM企业域信任Azure AD账号接管
1Password1Password云E2EE(SRP + Secret Key)1Password密钥主密码泄露、Secret Key泄露
BitwardenBitwarden云E2EE(PBKDF2/Argon2)主密码+加密密钥主密码泄露

密钥生命周期取证

完整的密钥生命周期取证需要追踪密钥从创建到销毁的全过程。以下分析框架适用于不同平台的Passkey密钥。

生命周期阶段取证数据源关键信息时间精度
密钥生成RP认证日志+设备日志密钥ID、算法、时间戳秒级
密钥注册WebAuthn Attestation日志认证器信息、RP ID秒级
密钥使用RP认证日志Assertion数据、时间戳秒级
密钥同步平台同步服务日志同步设备列表、时间戳分钟级
密钥导出平台导出操作日志导出目标、授权信息秒级
密钥删除RP认证日志+设备日志删除操作来源、时间戳秒级

0x05 Passkey中继攻击与欺骗检测

BLE-to-Cloud中继攻击架构

BLE中继攻击(MITRE ATT&CK T1557)是针对Passkey最复杂也最危险的攻击方式之一。攻击者在受害者附近部署BLE中继设备,在远程服务器上架设云端中继,将受害者的Passkey认证操作实时转发到攻击者的设备上,使RP服务器误认为是合法的受害者认证。

┌──────────┐    BLE    ┌──────────────┐    HTTPS    ┌──────────────┐    BLE    ┌──────────┐
│  Victim   │<-------->|  BLE Relay   |<--Cloud---->|  C2 Server   |<-------->| Attacker  │
│  Device   │  近距离   │  (Nearby)    │   中继链    │  (Remote)    │  远程    │  Device   │
│  (Passkey)│  ~5m     │  Raspberry   │             │  VPS/SaaS    │         │  (Clone)  │
└──────────┘          │  Pi + BLE    │             │              │         └──────────┘
                      │  Adapter     │             │              │
                      └──────────────┘             └──────────────┘

攻击流程:
1. BLE嗅探器检测到附近Passkey设备的BLE广播
2. 攻击者触发RP发起WebAuthn认证请求
3. BLE中继设备拦截CTAP2 GetAssertion请求
4. 通过Cloud中继将请求转发到攻击者设备
5. 攻击者设备在无受害者交互的情况下响应
6. 响应通过中继链返回RP服务器

NFC中继攻击

NFC中继攻击(MITRE ATT&CK T1557.006)利用NFC通信的短距离特性,通过专用中继设备扩展NFC通信的有效距离。与BLE中继不同,NFC中继需要更精密的硬件设备和更低的延迟。

中继攻击类型攻击设备延迟要求硬件成本成功率取证线索
BLE中继Raspberry Pi + BLE Dongle<500msBLE日志异常
NFC中继Proxmark3 + 双天线<100msNFC操作时序异常
USB中继USB Redirection设备<10msUSB连接模式异常
Cloud中继VPS + WebSocket<200msIP地理位置异常

近场验证绕过技术

近场验证(Proximity Verification)是防止中继攻击的关键防线。主要的近场验证机制包括超声波验证、信号强度(RSSI)检测、时间飞行(ToF)测量等。攻击者已经开发出多种绕过这些验证的手段。

近场验证机制验证原理绕过方式检测难度
RSSI信号强度检测BLE/NFC信号强度判断距离功率放大器 + 信号衰减模拟
超声波验证设备间超声波距离测量超声波中继设备
时间飞行(ToF)信号往返时间测量高速中继 + 预测响应极高
Wi-Fi RTTWi-Fi飞行时间测量Wi-Fi信号中继
地理位置绑定检查认证设备GPS坐标GPS欺骗

中继攻击检测签名

在取证分析中,可以通过以下模式识别中继攻击的痕迹。这些检测签名可集成到自动化检测系统中。

检测维度正常模式中继攻击模式检测方法
BLE RSSI稳定在-40至-70dBm波动大或异常低RSSI时序分析
认证延迟<200ms端到端>500ms(含网络延迟)时序分析
IP地理位置用户常驻位置远程位置或频繁变化GeoIP分析
设备指纹一致的设备特征浏览器/OS指纹矛盾指纹对比
认证时间合理的工作/休息时间异常时间段时间模式分析
并发会话单一活跃会话多地并发活跃会话会话状态分析
BLE连接模式短暂有序的GATT操作长时间持续连接连接时序分析

中继攻击日志分析模式

log stream --predicate 'subsystem == "com.apple.bluetooth" AND eventMessage CONTAINS "CTAP2"' --info
日志字段正常值范围异常值范围分析工具
BLE连接间隔15-30ms<10ms或>100msBLE日志解析
CTAP2消息往返<50ms(本地)>200ms(中继延迟)时序分析脚本
GATT操作次数3-10次/认证>20次/认证流量统计
RSSI变化率<5dBm/秒>10dBm/秒RSSI分析

0x06 设备同步链完整性取证

Apple iCloud Keychain同步链分析

Apple的Passkey同步基于iCloud Keychain基础设施。密钥通过端到端加密(E2EE)同步到用户的所有Apple设备。当启用Advanced Data Protection时,同步数据额外受到iCloud密钥的保护。

同步链架构:

┌──────────────┐
│ iCloud Keychain│
│  Sync Server  │
└──────┬───────┘
       │ E2EE Sync
       ├──────────────┬──────────────┬──────────────┐
       │              │              │              │
  ┌────┴────┐   ┌────┴────┐   ┌────┴────┐   ┌────┴────┐
  │ iPhone   │   │ MacBook  │   │ iPad     │   │ Mac     │
  │ (Primary)│   │ (Synced) │   │ (Synced) │   │ (Synced) │
  │ SE       │   │ SE       │   │ SE       │   │ SE       │
  └─────────┘   └─────────┘   └─────────┘   └─────────┘

iCloud Keychain同步链取证:

取证数据源命令/方法获取信息
密钥链记录security dump-keychain密钥条目元数据
同步状态security cms -D -i ~/Library/Keychains/*/keychain-band.db同步链状态
设备列表Apple ID设备管理页面关联设备信息
恢复密钥钥匙串访问应用Recovery Key状态
security find-generic-password -s "passkey" -a "user@example.com" -l "WebAuthn Credential" -g 2>&1 | head -30
security dump-keychain -d login.keychain-db 2>&1 | grep -i "passkey\|fido\|webauthn"

Google Password Manager跨设备同步

Google的Passkey同步基于Google Password Manager服务。密钥在Android设备间通过Google账号同步,在Chrome浏览器间通过Google Smart Lock同步。

同步路径加密方式同步范围取证特征
Android ↔ AndroidE2EE已登录同一Google账号的Android设备Android Keychain日志
Chrome ↔ ChromeE2EE已登录同一Google账号的ChromeChrome Sync日志
Android → ChromeE2EE通过Google Password Manager桥接跨平台同步事件
第三方密码管理器管理器自身的E2EE管理器支持的所有平台密码管理器日志

Windows Hello跨设备Passkey

Windows 11支持通过Microsoft Account同步Passkey。同步的密钥存储在Microsoft的云服务中,登录时通过Windows Hello生物识别或PIN码解锁。

Get-WinEvent -LogName "Microsoft-Windows-Hello-FIDO/Operational" -MaxEvents 50 |
    Where-Object { $_.Id -in @(300, 301, 400, 401) } |
    Format-List TimeCreated, Id, Message

同步协议安全性验证

跨设备同步的安全性取决于密钥在传输和存储过程中的加密保护。以下检查框架用于验证同步链的安全状态。

检查项安全状态风险等级检查方法
E2EE启用✅ 密钥端到端加密检查同步服务配置
恢复密钥保护✅ 恢复密钥已安全存储验证Recovery Key状态
设备信任链✅ 所有设备均为已知设备对比设备列表
同步延迟✅ 正常同步延迟检查同步时间戳
未授权设备❌ 发现未授权设备严重设备列表审计
同步中断⚠️ 同步服务异常检查同步日志

未授权设备检测

检测同步链中是否被注入了未授权设备是Passkey取证的关键环节。攻击者可能通过入侵用户云端账号添加恶意设备到同步链中。

log show --predicate 'process == "cloudd" AND eventMessage CONTAINS "keychain"' --last 24h | \
    grep -E "device|sync|add|remove" | \
    sort -k1,2
检测维度正常指标异常指标取证工具
设备数量稳定(用户已知设备数)突然增加平台设备管理API
设备类型用户已知设备型号未知设备型号设备指纹数据库
设备地理位置用户常驻位置异地设备IP/设备定位
首次同步时间合理的时间分布异常的首次同步时间同步时间线分析
同步频率正常的周期性同步高频或零同步同步模式分析

密钥导出/导入取证痕迹

Passkey的导出/导入操作在取证中具有重要价值,因为这些操作可能指示密钥迁移或攻击者试图窃取密钥。

操作类型平台支持取证痕迹MITRE ATT&CK
iCloud密钥链导出macOS Keychain Access导出操作日志、文件创建记录T1555 Credentials from Password Stores
Google密码导出Chrome设置导出CSV创建记录T1555 Credentials from Password Stores
FIDO2密钥备份认证器特定Backup操作日志T1555 Credentials from Password Stores
第三方密码管理器导出管理器特定导出日志+文件T1555 Credentials from Password Stores
硬件Security Key重置管理工具日志重置操作日志T1562 Impair Defenses

0x07 认证日志重建与异常行为检测

WebAuthn事件日志标准

各主流平台和RP在WebAuthn事件日志的记录格式和内容上存在差异。标准化的日志收集和分析框架对于跨平台取证至关重要。

平台/服务日志位置事件类型时间精度格式
Azure ADSign-in LogsWebAuthn认证秒级JSON
OktaSystem LogWebAuthn操作毫秒级JSON
Google WorkspaceAdmin Audit LogPasskey事件秒级JSON
AWS CognitoCloudWatch LogsFIDO2事件毫秒级JSON
自建RP应用日志自定义取决于实现自定义

Relying Party认证日志分析

RP端的日志是Passkey取证的核心数据源。标准的WebAuthn认证日志应包含以下关键字段。

日志字段数据类型描述取证用途
timestampISO 8601操作时间戳时序分析
event_typeEnumcreate/get/error操作类型识别
user_idString用户标识用户行为关联
credential_idBase64URL凭据标识密钥追踪
rp_idStringRelying Party标识RP关联
authenticator_typeEnumplatform/roaming认证器类型
attestation_fmtEnumpacked/tpmt/apple/none认证器来源
user_verificationBoolean用户验证结果UV状态检查
sign_countInteger签名计数器克隆检测
originURL请求来源Origin钓鱼检测
challengeBase64URLChallenge值Challenge验证

RP端日志分析脚本:

import json
import sys
from datetime import datetime, timedelta
from collections import defaultdict

def analyze_rp_auth_logs(log_file):
    events = []
    with open(log_file) as f:
        for line in f:
            try:
                events.append(json.loads(line.strip()))
            except json.JSONDecodeError:
                continue

    user_events = defaultdict(list)
    for event in events:
        uid = event.get("user_id", "unknown")
        user_events[uid].append(event)

    anomalies = []
    for uid, evts in user_events.items():
        sorted_evts = sorted(evts, key=lambda x: x.get("timestamp", ""))

        for i in range(1, len(sorted_evts)):
            prev = sorted_evts[i - 1]
            curr = sorted_evts[i]
            try:
                t_prev = datetime.fromisoformat(prev["timestamp"].replace("Z", "+00:00"))
                t_curr = datetime.fromisoformat(curr["timestamp"].replace("Z", "+00:00"))
                delta = (t_curr - t_prev).total_seconds()

                if delta < 1.0 and prev.get("credential_id") != curr.get("credential_id"):
                    anomalies.append({
                        "user_id": uid,
                        "type": "RAPID_CREDENTIAL_SWITCH",
                        "detail": f"Credential switch in {delta:.2f}s",
                        "severity": "HIGH",
                        "mitre": "T1557",
                        "events": [prev.get("timestamp"), curr.get("timestamp")]
                    })

                if prev.get("origin", "") != curr.get("origin", ""):
                    anomalies.append({
                        "user_id": uid,
                        "type": "ORIGIN_CHANGE",
                        "detail": f"Origin changed: {prev.get('origin')} -> {curr.get('origin')}",
                        "severity": "HIGH",
                        "mitre": "T1566",
                        "events": [prev.get("timestamp"), curr.get("timestamp")]
                    })

                if curr.get("sign_count", 0) < prev.get("sign_count", 0):
                    anomalies.append({
                        "user_id": uid,
                        "type": "SIGN_COUNT_DECREASE",
                        "detail": f"Count decreased: {prev.get('sign_count')} -> {curr.get('sign_count')}",
                        "severity": "CRITICAL",
                        "mitre": "T1557",
                        "events": [prev.get("timestamp"), curr.get("timestamp")]
                    })

            except (ValueError, KeyError):
                continue

    return anomalies

if __name__ == "__main__":
    target = sys.argv[1] if len(sys.argv) > 1 else "auth_logs.jsonl"
    results = analyze_rp_auth_logs(target)
    print(json.dumps(results, indent=2, ensure_ascii=False))

浏览器级Passkey遥测

浏览器作为WebAuthn API的宿主环境,提供了额外的遥测数据源。Chrome、Firefox和Safari在Passkey操作的记录方式上各有特色。

浏览器遥测数据源数据获取方式信息丰富度
Chromechrome://flags/#webauthn标志位+控制台日志
Chromechrome://system系统信息转储
Firefoxabout:config配置项日志
SafariWebKit Inspector开发者工具日志

操作系统级Authenticator事件日志

操作系统层面提供了Passkey操作的底层日志,这些日志对于还原完整的认证事件链至关重要。

操作系统日志系统日志命令关键过滤条件
WindowsWindows Event LogGet-WinEventMicrosoft-Windows-Hello-FIDO
macOSUnified Loglog show/streamcom.apple.fido / passkeyd
Androidlogcatadb logcatFido2Manager / WebAuthnManager
iOSUnified Logsysdiagnosecom.apple.passkeyd
Linuxjournaldjournalctlfido2 / libfido2

Windows综合取证脚本:

$logNames = @(
    "Microsoft-Windows-Hello-FIDO/Operational",
    "Microsoft-Windows-WebAuthN/Operational",
    "Security"
)

foreach ($logName in $logNames) {
    try {
        $events = Get-WinEvent -LogName $logName -MaxEvents 500 -ErrorAction SilentlyContinue |
            Where-Object { $_.TimeCreated -gt (Get-Date).AddDays(-7) }
        $events | ForEach-Object {
            [PSCustomObject]@{
                LogName = $logName
                TimeCreated = $_.TimeCreated
                EventId = $_.Id
                LevelDisplayName = $_.LevelDisplayName
                Message = $_.Message.Substring(0, [Math]::Min(200, $_.Message.Length))
            }
        } | Export-Csv -Path "passkey_audit_$logName.csv" -NoTypeInformation
    } catch {
        Write-Warning "Failed to read log: $logName"
    }
}

异常行为检测模式

以下异常检测模式综合了Passkey认证场景的常见攻击特征,可集成到SIEM或自动化检测平台中。

检测模式异常描述MITRE ATT&CK检测置信度响应优先级
Impossible Travel用户在不可能的时间内从两个远距离位置认证T1078 Valid Accounts紧急
设备指纹异常认证设备指纹与历史记录不匹配T1557 MITM紧急
时序异常认证时间模式明显偏离历史基线T1078 Valid Accounts
注册激增短时间内大量新Passkey注册T1199 Trusted Relationship
同步链异常同步链中出现未知设备T1550 Use Alternate Auth Material紧急
Sign Count异常签名计数器不单调递增或异常跳变T1557 MITM紧急
Origin不一致认证Origin与预期RP域名不符T1566 Phishing紧急
批量认证同一Credential短时间内多次认证T1078 Valid Accounts

0x08 跨平台Passkey实现差异与取证要点

Apple Passkey实现(iOS 16+ / macOS Ventura+)

Apple是Passkey的最早推动者之一,其实现深度集成了Apple生态系统。Apple Passkey基于Secure Enclave生成和存储密钥,通过iCloud Keychain实现跨设备同步,并与iCloud Advanced Data Protection集成提供端到端加密保护。

Apple Passkey特性描述取证要点
密钥存储Secure Enclave硬件隔离无法直接提取私钥
同步机制iCloud Keychain E2EE需要iCloud日志分析
平台认证器Touch ID / Face ID生物识别验证日志
Attestation格式apple attestationApple根证书链验证
密钥导出不支持直接导出检查导出尝试痕迹
恢复机制Recovery Key / 账号恢复恢复操作日志
Enterprise管理MDM配置描述文件企业策略审计
log show --predicate 'subsystem == "com.apple.passkeyd"' --last 24h --style json
log stream --predicate 'process == "credd" AND eventMessage CONTAINS "keychain sync"' --info
security find-generic-password -s "passkey" -l "WebAuthn" 2>&1

Google Passkey实现(Android 14+ / Chrome)

Google的Passkey实现横跨Android平台和Chrome浏览器两个主要渠道。Android端使用Keystore/StrongBox存储密钥,Chrome端使用Google Password Manager管理密钥。

Google Passkey特性描述取证要点
密钥存储Android Keystore / StrongBoxAndroid KeyStore审计
同步机制Google Password ManagerGoogle账号活动日志
平台认证器Android BiometricPrompt生物识别日志
Attestation格式android-key / android-safetynetGoogle设备认证验证
Chrome集成WebAuthn API + Chrome SyncChrome同步日志
跨平台Android ↔ Chrome跨平台同步事件
adb logcat -b all | grep -iE "fido|passkey|webauthn|biometric"
adb shell dumpsys credential_manager
adb shell content query --uri content://com.google.android.apps.authkeeper.data.provider --projection event

Windows Hello/Passkey实现

Windows平台通过Windows Hello提供平台认证器功能,密钥存储在TPM 2.0中。Windows 11开始支持通过Microsoft Account同步Passkey,并支持第三方FIDO2 Security Key。

Windows Passkey特性描述取证要点
密钥存储TPM 2.0TPM事件日志
同步机制Microsoft AccountAzure AD登录日志
平台认证器Windows Hello (PIN/指纹/面部)Hello事件日志
Attestation格式tpmtTPM证书链验证
企业集成Azure AD / Active Directory域控审计日志
第三方支持FIDO2 Security KeyUSB HID日志

第三方密码管理器Passkey支持

随着Passkey的普及,主流密码管理器也纷纷集成Passkey支持,作为跨平台同步的替代方案。不同密码管理器的实现安全特性差异显著。

密码管理器平台支持密钥存储同步加密Attestation安全审计
1PasswordWin/Mac/Linux/iOS/Android安全飞轮+Secure EnclaveE2EE (SRP + Secret Key)无attestationSOC 2 Type II
BitwardenWin/Mac/Linux/iOS/Android本地加密存储E2EE (主密码)无attestation第三方审计
DashlaneWin/Mac/iOS/Android安全保险库E2EE无attestationSOC 2
KeePassXCWin/Mac/Linux本地数据库文件无云同步无attestation社区审计
Proton PassWin/Mac/iOS/AndroidProton加密层E2EE (Proton)无attestation第三方审计

跨平台取证方法对比

不同平台的取证方法、数据源和工具存在显著差异。以下对比表提供了跨平台取证的方法论框架。

取证环节AppleGoogleWindows第三方管理器
密钥枚举security命令+Keychain日志Android KeyStore日志TPM日志+Event Log管理器日志/数据库
认证日志Unified Log (com.apple.fido)logcat (Fido2Manager)Hello-FIDO Event Log管理器事件日志
同步链审计iCloud设备管理Google账号设备列表Microsoft Account设备管理器同步设置
密钥删除追踪Keychain审计日志KeyStore删除事件TPM密钥操作日志管理器日志
导出检测Keychain导出日志Google密码导出CSV无标准导出路径管理器导出日志
取证工具macOS内置Android SDKPowerShell管理器CLI/API
实时监控log streamlogcat实时Event Viewer实时管理器日志API
远程取证iCloud Web + 查找Google账号活动Azure AD日志管理器Web面板

0x09 证据强度分层与案例关联

🔴 确认恶意

无可争议的恶意行为证据。当出现以下证据时,可以确认发生了Passkey相关的安全事件。

编号证据类型具体示例确认依据MITRE ATT&CK
C-1未授权密钥创建RP日志显示在用户未操作时创建了新Passkey用户行为时序矛盾T1199 Trusted Relationship
C-2中继攻击确认BLE中继设备日志包含CTAP2消息转发记录完整的中继攻击链证据T1557 Man-in-the-Middle
C-3密钥窃取云端账号日志显示从未知设备导出了Passkey未授权的密钥导出操作T1555 Credentials from Password Stores
C-4同步链注入iCloud Keychain日志显示未知设备被添加到同步链未授权设备接入T1550 Use Alternate Auth Material
C-5签名计数器不一致RP日志显示Sign Count出现回退或异常跳变计数器回退表明密钥克隆T1557 Man-in-the-Middle
C-6Origin欺骗WebAuthn请求来自与RP域名不匹配的Origin伪造的认证来源T1566 Phishing
C-7恶意Browser Extension拦截浏览器扩展列表中发现拦截navigator.credentials的扩展明确的WebAuthn API劫持T1176 Browser Extensions

🟡 高度可疑

强烈暗示恶意活动但需要进一步验证的证据。

编号证据类型具体示例可疑原因MITRE ATT&CK
S-1异常注册模式新Passkey注册发生在用户非活跃时间段可能为自动化攻击T1078 Valid Accounts
S-2同步链新增设备同步链中出现未在用户管理中登记的设备可能为账号泄露T1550 Use Alternate Auth Material
S-3异常认证时序Passkey认证的端到端延迟显著高于基线可能为中继攻击T1557 Man-in-the-Middle
S-4设备指纹矛盾认证请求的User-Agent与已知设备不匹配可能为代理或伪造T1071 Application Layer Protocol
S-5认证器类型变更同一用户从platform认证器切换到roaming认证器可能为正常的硬件迁移T1550 Use Alternate Auth Material
S-6Challenge重用同一Challenge被用于多次认证尝试可能为重放攻击T1557 Man-in-the-Middle
S-7高频认证同一Credential短时间内认证次数异常可能为自动化攻击T1078 Valid Accounts

🟢 需要关注

可能为正常行为但需要结合上下文判断的证据。

编号证据类型具体示例关注原因MITRE ATT&CK
W-1平台认证器升级设备OS升级后Passkey认证器版本变化正常的系统更新N/A
W-2备份密钥创建用户创建了额外的备份Passkey可能为正常的多设备管理N/A
W-3跨平台同步活动Passkey从Android同步到Chrome正常的跨平台同步N/A
W-4Attestation格式变更新注册的Passkey使用了不同的Attestation格式可能为认证器更新N/A
W-5密码管理器注册在第三方密码管理器中注册了新的Passkey可能为用户主动管理N/A
W-6时区变化认证时区与用户旅行计划一致可能为正常旅行N/A
W-7认证失败后成功认证多次失败后成功可能为用户操作失误N/A

0x0A 自动化检测与狩猎

Sigma规则:FIDO2/Passkey认证异常检测

以下Sigma规则用于检测Passkey认证过程中的关键异常行为。

title: Suspicious Passkey Registration Activity
id: a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d
status: experimental
description: Detects suspicious Passkey registration events outside normal patterns
references:
  - https://attack.mitre.org/techniques/T1199/
author: x7peeps
date: 2026/07/22
tags:
  - attack.credential_access
  - attack.t1199
logsource:
  category: authentication
  product: multi
detection:
  selection_webauthn_create:
    EventId|contains:
      - '300'
      - '301'
  selection_off_hours:
    TimeCreated|re: '.*T(0[0-4]|2[2-3]):[0-5][0-9].*'
  selection_failed_then_success:
    EventId|contains: '302'
  condition: selection_webauthn_create and selection_off_hours
level: high
title: Passkey Sign Count Anomaly Detection
id: b2c3d4e5-f6a7-8b9c-0d1e-2f3a4b5c6d7e
status: experimental
description: Detects anomalies in FIDO2 signature counter values indicating potential key cloning
references:
  - https://attack.mitre.org/techniques/T1557/
author: x7peeps
date: 2026/07/22
tags:
  - attack.credential_access
  - attack.t1557
logsource:
  category: authentication
  product: multi
detection:
  selection_assertion:
    EventId|contains:
      - '400'
      - '401'
  selection_sign_count_drop:
    SignCount|lt: previous_sign_count
  condition: selection_assertion and selection_sign_count_drop
level: critical

Bash脚本:Passkey事件日志采集与分析器

以下脚本用于自动化采集和分析多平台Passkey事件日志。

#!/bin/bash
OUTPUT_DIR="passkey_forensics_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$OUTPUT_DIR"

collect_windows_events() {
    local log_names=(
        "Microsoft-Windows-Hello-FIDO/Operational"
        "Microsoft-Windows-WebAuthN/Operational"
        "Microsoft-Windows-WinINet/Operational"
    )
    for log_name in "${log_names[@]}"; do
        local safe_name=$(echo "$log_name" | tr '/' '_')
        powershell.exe -Command "
            Get-WinEvent -LogName '$log_name' -MaxEvents 1000 -ErrorAction SilentlyContinue |
            Where-Object { \$_.TimeCreated -gt (Get-Date).AddDays(-30) } |
            ConvertTo-Json -Depth 3
        " > "$OUTPUT_DIR/windows_${safe_name}.json" 2>/dev/null
    done
}

collect_macos_events() {
    local predicates=(
        'subsystem == "com.apple.fido"'
        'process == "securityd" AND eventMessage CONTAINS "passkey"'
        'subsystem == "com.apple.passkeyd"'
        'process == "credd" AND eventMessage CONTAINS "keychain"'
        'eventMessage CONTAINS "WebAuthn" OR eventMessage CONTAINS "CTAP2"'
    )
    for i in "${!predicates[@]}"; do
        log show --predicate "${predicates[$i]}" --last 30d --style json \
            > "$OUTPUT_DIR/macos_predicate_${i}.json" 2>/dev/null
    done
}

collect_android_events() {
    if command -v adb &>/dev/null; then
        adb logcat -b all -d | grep -iE "fido|passkey|webauthn|biometric|credential" \
            > "$OUTPUT_DIR/android_logcat.txt" 2>/dev/null
        adb shell dumpsys credential_manager \
            > "$OUTPUT_DIR/android_credential_manager.txt" 2>/dev/null
    fi
}

analyze_risk_patterns() {
    echo "=== Passkey Forensics Risk Analysis ==="
    echo "Output directory: $OUTPUT_DIR"
    echo ""
    if [[ "$OSTYPE" == "darwin"* ]]; then
        local webauthn_count=$(grep -c -i "webauthn\|passkey\|fido" "$OUTPUT_DIR"/macos_*.json 2>/dev/null || echo 0)
        echo "macOS WebAuthn/Passkey events found: $webauthn_count"
    elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" ]]; then
        echo "Windows event files collected:"
        ls -la "$OUTPUT_DIR"/windows_*.json 2>/dev/null
    fi
    echo ""
    echo "Review $OUTPUT_DIR/ for detailed forensic data."
}

case "$(uname -s)" in
    Darwin)   collect_macos_events ;;
    Linux)    collect_android_events ;;
    MINGW*|CYGWIN*)  collect_windows_events ;;
esac

analyze_risk_patterns

Python脚本:WebAuthn Assertion异常检测器

import json
import sys
import hashlib
from datetime import datetime
from collections import defaultdict
from math import radians, sin, cos, sqrt, atan2

GEOLOC_DB = {
    "US": (37.0902, -95.7129),
    "CN": (35.8617, 104.1954),
    "JP": (36.2048, 138.2529),
    "DE": (51.1657, 10.4515),
    "GB": (55.3781, -3.4360),
}

def haversine(lat1, lon1, lat2, lon2):
    R = 6371
    dlat = radians(lat2 - lat1)
    dlon = radians(lon2 - lon1)
    a = sin(dlat/2)**2 + cos(radians(lat1)) * cos(radians(lat2)) * sin(dlon/2)**2
    return R * 2 * atan2(sqrt(a), sqrt(1-a))

class PasskeyAnomalyDetector:
    def __init__(self):
        self.alerts = []
        self.user_profiles = defaultdict(lambda: {
            "locations": [],
            "credential_ids": set(),
            "authenticator_types": set(),
            "timestamps": [],
            "sign_counts": {},
            "origins": set(),
            "user_agents": set()
        })

    def ingest_event(self, event):
        uid = event.get("user_id", "unknown")
        profile = self.user_profiles[uid]
        ts_str = event.get("timestamp", "")
        if ts_str:
            try:
                ts = datetime.fromisoformat(ts_str.replace("Z", "+00:00"))
                profile["timestamps"].append(ts)
            except ValueError:
                pass
        cred_id = event.get("credential_id", "")
        if cred_id:
            profile["credential_ids"].add(cred_id)
        auth_type = event.get("authenticator_type", "")
        if auth_type:
            profile["authenticator_types"].add(auth_type)
        origin = event.get("origin", "")
        if origin:
            profile["origins"].add(origin)
        ua = event.get("user_agent", "")
        if ua:
            profile["user_agents"].add(ua)
        sign_count = event.get("sign_count", -1)
        if cred_id and sign_count >= 0:
            prev = profile["sign_counts"].get(cred_id, -1)
            if prev >= 0:
                if sign_count < prev:
                    self._alert(uid, "SIGN_COUNT_REVERSE",
                                f"Count {prev} -> {sign_count}", "CRITICAL", "T1557")
                elif sign_count - prev > 100:
                    self._alert(uid, "SIGN_COUNT_JUMP",
                                f"Jump +{sign_count - prev}", "HIGH", "T1557")
            profile["sign_counts"][cred_id] = sign_count
        loc = event.get("geo_country", "")
        if loc:
            profile["locations"].append((ts_str, loc))
        self._check_impossible_travel(uid, profile)
        self._check_multi_origin(uid, profile)

    def _check_impossible_travel(self, uid, profile):
        locs = profile["locations"]
        if len(locs) < 2:
            return
        for i in range(1, len(locs)):
            ts_prev, c_prev = locs[i-1]
            ts_curr, c_curr = locs[i]
            if c_prev == c_curr or c_prev not in GEOLOC_DB or c_curr not in GEOLOC_DB:
                continue
            try:
                t1 = datetime.fromisoformat(ts_prev.replace("Z", "+00:00"))
                t2 = datetime.fromisoformat(ts_curr.replace("Z", "+00:00"))
                hours = abs((t2 - t1).total_seconds()) / 3600
                dist = haversine(*GEOLOC_DB[c_prev], *GEOLOC_DB[c_curr])
                speed = dist / max(hours, 0.01)
                if speed > 900:
                    self._alert(uid, "IMPOSSIBLE_TRAVEL",
                                f"{c_prev}->{c_curr} {dist:.0f}km in {hours:.1f}h ({speed:.0f}km/h)",
                                "CRITICAL", "T1078")
            except (ValueError, KeyError):
                continue

    def _check_multi_origin(self, uid, profile):
        if len(profile["origins"]) > 3:
            self._alert(uid, "MULTI_ORIGIN",
                        f"Multiple origins: {profile['origins']}", "HIGH", "T1566")

    def _alert(self, uid, atype, detail, severity, mitre):
        self.alerts.append({
            "user_id": uid,
            "alert_type": atype,
            "detail": detail,
            "severity": severity,
            "mitre": mitre,
            "timestamp": datetime.utcnow().isoformat() + "Z"
        })

    def generate_report(self):
        return {
            "total_alerts": len(self.alerts),
            "critical": [a for a in self.alerts if a["severity"] == "CRITICAL"],
            "high": [a for a in self.alerts if a["severity"] == "HIGH"],
            "all_alerts": self.alerts
        }

if __name__ == "__main__":
    detector = PasskeyAnomalyDetector()
    logfile = sys.argv[1] if len(sys.argv) > 1 else "rp_auth_logs.jsonl"
    try:
        with open(logfile) as f:
            for line in f:
                try:
                    detector.ingest_event(json.loads(line.strip()))
                except json.JSONDecodeError:
                    continue
    except FileNotFoundError:
        print(json.dumps({"error": f"File not found: {logfile}"}))
        sys.exit(1)
    report = detector.generate_report()
    print(json.dumps(report, indent=2, ensure_ascii=False))

YARA规则:恶意认证器识别

rule FIDO2_Malicious_Authenticator {
    meta:
        description = "Detects indicators of malicious FIDO2 authenticator implementations"
        author = "x7peeps"
        date = "2026-07-22"
        reference = "Passkey Security Forensics"
        mitre_attck = "T1557,T1199"
    strings:
        $ctap_header = { 80 01 ?? 02 ?? 03 }
        $webauthn_api = "navigator.credentials" ascii
        $fido_service = "FIDO" ascii nocase
        $suspicious_origin = "javascript:" ascii
        $relay_marker = "ble-relay" ascii nocase
        $fake_attestation = "attStmt" ascii
        $challenge_reuse = "replay" ascii nocase
    condition:
        ($webauthn_api and $suspicious_origin) or
        ($relay_marker and $fido_service) or
        ($ctap_header and $fake_attestation and $challenge_reuse)
}

rule CTAP2_Credential_Cloning_Indicators {
    meta:
        description = "Detects indicators of CTAP2 credential cloning attempts"
        author = "x7peeps"
        date = "2026-07-22"
        mitre_attck = "T1557,T1550"
    strings:
        $ctap_msg = { 80 10 }
        $ctap_init = { 80 86 }
        $sign_counter_zero = { 00 00 00 00 }
        $get_assertion_cmd = { 80 01 }
        $make_cred_cmd = { 80 01 }
    condition:
        $ctap_msg and $sign_counter_zero and $get_assertion_cmd
}

0x0B 公开案例分析

案例一:Passkey Phishing中继攻击活动(2024)

2024年,安全研究人员披露了一起针对企业用户的Passkey中继攻击活动。攻击者通过精心构造的钓鱼页面诱导用户在攻击者控制的域名上发起WebAuthn认证,同时在后台通过BLE中继设备将CTAP2消息实时转发到受害者的真实设备,完成看似合法的Passkey认证。

攻击链还原:

阶段1: 初始访问
  攻击者发送钓鱼邮件 → 受害者点击链接 → 访问伪造的RP登录页面

阶段2: 会话劫持
  伪造页面加载合法RP的WebAuthn JS库 → 调用navigator.credentials.get()
  浏览器触发CTAP2 GetAssertion → BLE中继设备拦截请求

阶段3: 中继认证
  中继设备通过WebSocket转发到C2服务器 → 攻击者页面显示认证进度
  受害者设备完成用户验证(生物识别) → 私钥签名Challenge
  签名通过中继链返回 → 伪造页面提交到真实RP → 认证成功

阶段4: 后渗透
  攻击者获得受害者会话 → 访问企业内部系统 → 横向移动

取证发现:

取证环节发现严重度
RP认证日志Origin字段显示攻击者域名而非合法RP域名严重
BLE流量日志认证期间BLE连接持续时间异常(15秒 vs 正常3秒)
时序分析CTAP2消息往返延迟450ms(正常<50ms)
设备指纹User-Agent显示Chrome但认证器为platform类型
网络日志认证期间存在异常WebSocket连接到外部IP

IOC(Indicators of Compromise):

IOC类型IOC值描述
域名auth-verify-login[.]com钓鱼域名
IP185.xx.xx.42C2中继服务器
文件哈希SHA256: a1b2c3…恶意浏览器扩展安装包
WebSocketwss://relay-ctl[.]com/ws中继控制通道
扩展IDchrome-extension://abcdef123456拦截WebAuthn的恶意扩展

案例二:Yubico Security Key固件漏洞与Passkey影响(2024)

2024年,安全研究人员发现特定版本的Yubico Security Key固件在处理CTAP2 MakeCredential请求时存在缓冲区溢出漏洞。攻击者可以构造特殊的attestation请求来触发内存损坏,可能导致密钥泄露或认证器行为异常。

攻击链还原:

阶段1: 漏洞触发
  攻击者控制的RP发送特制的MakeCredential请求
  → rp.id字段超长输入 → CTAP2解析器缓冲区溢出

阶段2: 影响评估
  潜在影响: 认证器crash重启、内存内容泄露、attestation伪造
  实际利用难度: 需要物理接触或恶意RP服务器

阶段3: 检测与响应
  Yubico发布固件更新 → 强制固件降级保护机制
  安全社区审计CTAP2解析器代码 → 发现多个类似问题

取证发现:

取证环节发现严重度
USB HID日志MakeCredential请求rp.id字段异常长度(>256字节)
认证器响应CTAP2 Error Response code 0x35(CBOR parsing error)
系统日志认证器crash后重新初始化事件
固件版本受影响固件版本号记录
RP服务器日志使用异常rp.id的注册请求

IOC(Indicators of Compromise):

IOC类型IOC值描述
固件版本<5.2.7受影响的Yubico固件版本
USB HID数据rp.id长度>256字节的MakeCredential溢出触发特征
CTAP2错误码0x35CBOR解析错误
CTAP2状态码CTAP1_ERR_OTHER认证器异常响应

0x0C 参考资料

编号资料名称URL描述
1FIDO Alliance CTAP 2.2 Specificationhttps://fidoalliance.org/specs/fido-v2.2-rd-20230321/client-to-authenticator-protocol-v2.2-rd-20230321.htmlCTAP2协议完整规范
2W3C Web Authentication Level 3https://www.w3.org/TR/webauthn-3/WebAuthn API Level 3规范
3FIDO Alliance Passkey Whitepaperhttps://fidoalliance.org/passkeys/Passkey概念和架构白皮书
4Apple Platform Security Guide - Passkeyshttps://support.apple.com/guide/security/passkeys-sec9c012766e/webApple Passkey安全架构
5Google Passkey Security Designhttps://developers.google.com/identity/passkeys/supported-environmentsGoogle Passkey安全设计文档
6Microsoft Windows Hello for Businesshttps://learn.microsoft.com/en-us/windows/security/identity-protection/hello-for-business/Windows Hello架构与安全
7W3C WebAuthn Level 3 - Implementation Guidehttps://webauthn.guide/WebAuthn开发者实施指南
8FIDO Alliance Security Requirementshttps://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html#sctn-security-requirementsCTAP2安全要求规范
9NIST SP 800-63B - Digital Identity Guidelineshttps://pages.nist.gov/800-63-3/sp800-63b.html数字身份认证指南
10CVE-2024-3094 XZ Utils Backdoorhttps://nvd.nist.gov/vuln/detail/CVE-2024-3094供应链攻击参考案例

免责声明: 本文仅供安全研究和取证分析学习之用。文中涉及的攻击技术描述旨在帮助安全专业人员理解和防御此类攻击。未经授权对他人系统实施任何形式的攻击均属违法行为。所有取证分析操作都应遵循当地法律法规,并在获得适当授权的前提下进行。