✓ 已显示
对于捆绑包中的每个条目,判定结果显示签发方(ACME、GitHub、AWS)、账户名称(alice@acme.com)、算法(SHA1)、位数(6)以及类型(TOTP)。判定结果披露内容显示为"此捆绑包中的授权:ACME / alice@acme.com;GitHub / bob@github;AWS / root;……",以便正在进行迁移的用户在导入前可以核查列表。
架构版本、分块索引、分块总数和分块ID也会显示,在导出内容被分散到多个QR时非常有用。
Google Authenticator及若干兼容应用(Aegis、Raivo OTP、2FAS)允许您"导出"已存储的双重验证账户,以便迁移到新设备。导出形式为一个URI以 otpauth-migration:// 开头的QR码。该URI内部是一个单一的protocol buffer捆绑包(Google的MigrationPayload架构),一次性携带所有账户信息——签发方、账户名称、种子密钥、算法、位数、类型(HOTP / TOTP)及计数器。
该格式最初没有文档记录,但已被逆向工程,现已成为双重验证备份的事实标准交换格式。第三方身份验证器应用可识别并导入同一QR。
一个QR可能包含数十个账户。该QR在视觉上与普通TOTP设置QR无法区分——没有任何视觉标记向旁观者表明它携带了整个捆绑包。
普通的 otpauth:// 设置QR如果不是您主动请求的,扫描本身就有风险,但影响范围仅限于一个账户。迁移QR的影响范围是您身份验证器中的所有账户。如果攻击者拍摄了显示该QR的屏幕——在咖啡馆从您身后拍、通过您未注意到的监控摄像头拍、透过透明玻璃窗拍——他们就永久获得了绕过该捆绑包所涵盖所有账户双重验证的能力。直到您逐个账户手动更换密钥,而大多数服务并不提供便捷的轮换方式。
捆绑包中的密钥没有到期时间。不同于会话令牌(会过期),不同于通行密钥QR(一次性使用),迁移捆绑包中的种子在您逐一替换之前始终有效。
这就是为何我们的扫描仪对每个 otpauth-migration:// QR的判定都以likely_dangerous(极可能危险)开始,且不因具体情境而改变。格式本身没有问题,威胁来自该格式存在本身。
URI格式如下:
otpauth-migration://offline?data=<urlsafe-base64-encoded-protobuf>
base64正文解码后,是一个包含以下顶层字段的 MigrationPayload protocol buffer:
每个 otp_parameters 条目包含:
alice@acme.com)。ACME、GitHub)。对于捆绑包中的每个条目,判定结果显示签发方(ACME、GitHub、AWS)、账户名称(alice@acme.com)、算法(SHA1)、位数(6)以及类型(TOTP)。判定结果披露内容显示为"此捆绑包中的授权:ACME / alice@acme.com;GitHub / bob@github;AWS / root;……",以便正在进行迁移的用户在导入前可以核查列表。
架构版本、分块索引、分块总数和分块ID也会显示,在导出内容被分散到多个QR时非常有用。
原始 secret 字节永远不会被解码输出到判定结果中。我们的分析器只读取这些字节以验证每个条目的格式是否正确(密钥存在且非空),之后在构建结果前即丢弃该值。
此行为通过测试套件进行断言——我们向分析器输入包含金丝雀字符串(SECRET_SEED_1、SECRET_SEED_2)的手工protobuf载荷,并断言这些字符串永远不会出现在序列化的判定结果输出中。此处的回归将导致CI失败。
合法使用场景:您正在从旧手机换到新手机。旧手机在屏幕上显示迁移QR约30秒。新手机的身份验证器应用对准屏幕完成导入。房间里没有其他人。确认全部导入成功后,从旧手机删除导出内容。
危险情形包括:
将其视为捆绑包内所有账户的凭证泄露。按顺序执行的恢复步骤:
获得捆绑包的攻击者可以在您轮换之前持续数年生成有效的双重验证码。请勿拖延。
将QR图像拖入我们的扫描仪,粘贴 otpauth-migration:// URI,或使用摄像头。判定结果显示捆绑包中的每个账户,且不解码任何密钥。