CVE-2024-39924
Executive Summary
CVE-2024-39924 is a privilege escalation vulnerability in Vaultwarden (formerly Bitwarden_RS) version 1.30.3. The flaw resides in the authentication and authorization logic of the endpoint responsible for modifying emergency access metadata. An attacker who has been granted emergency access can exploit this vulnerability to escalate their privileges by altering the access level (e.g., from read-only to full control) and modifying the required wait time. This allows the attacker to gain full control over the target vault without waiting the intended period, effectively bypassing the security controls designed for emergency access scenarios.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Vaultwarden is an open-source, self-hosted password manager written in Rust. It is distributed as a Docker image and via GitHub releases. The vulnerability affects the core application logic and is not related to a specific package manager (NPM, PyPI, Go, Ruby). However, organizations using Vaultwarden should verify the integrity of their deployment artifacts and monitor for official patches or updated Docker images.
CVSS Breakdown & Threat Level
The CVSS score is listed as 0.0, indicating that a full vector has not been assigned by NVD at this time. Based on the vulnerability description, a reasonable estimated vector would be:
- Attack Vector (AV): Network (the emergency access feature is network-accessible)
- Attack Complexity (AC): Low (the attacker only needs valid emergency access credentials)
- Privileges Required (PR): Low (attacker already has emergency access)
- User Interaction (UI): None
- Scope (S): Changed (the attacker can access the vault owner's data)
- Confidentiality (C): High
- Integrity (I): High
- Availability (A): None
Estimated CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N
Threat Level: High. The vulnerability allows a low-privileged attacker (emergency access user) to gain full read/write access to the vault owner's secrets.
Deep Dive & Mechanics
The vulnerability is located in the emergency access feature of Vaultwarden. This feature allows a user (the "grantor") to grant another user (the "grantee") access to their vault in case of emergency. The grantor can set an access level (read-only or full control) and a wait time (the period before the grantee can actually access the vault).
The flaw is in the API endpoint that handles updating the metadata of an emergency access grant. The endpoint does not properly validate that the grantee is only modifying their own access level and wait time within the bounds set by the grantor. An attacker who has been granted emergency access can send a crafted request to this endpoint, changing the access_level from "read" to "full" and setting the wait_time to zero or a very low value. The server then applies these changes without re-authorization, allowing the attacker to immediately take full control of the vault.
The root cause is a missing authorization check: the endpoint should verify that the grantee is only modifying parameters that the grantor has allowed them to change, and that any changes to the access level or wait time are within the grantor's original intent.
Vulnerable vs. Patched Code
Since no official patch is available, the following is a conceptual comparison.
Vulnerable Code (Conceptual Rust):
// In the emergency access update handler
#[post("/emergency-access/{id}/update")]
async fn update_emergency_access(
id: String,
data: Json<EmergencyAccessUpdate>,
user: User,
conn: DbConn,
) -> JsonResult {
let mut emergency_access = EmergencyAccess::find_by_id(&id, &conn).await?;
// Missing check: is the user the grantee of this emergency access?
// Missing check: is the user allowed to change the access level?
emergency_access.access_level = data.access_level;
emergency_access.wait_time = data.wait_time;
emergency_access.save(&conn).await?;
Ok(Json(json!({ "success": true })))
}
Patched Code (Conceptual Rust):
#[post("/emergency-access/{id}/update")]
async fn update_emergency_access(
id: String,
data: Json<EmergencyAccessUpdate>,
user: User,
conn: DbConn,
) -> JsonResult {
let emergency_access = EmergencyAccess::find_by_id(&id, &conn).await?;
// Verify the user is the grantee
if emergency_access.grantee_id != user.id {
return Err(Error::Unauthorized);
}
// Verify the grantee is only changing allowed fields
// For example, they cannot change the access level from read to full
if data.access_level != emergency_access.access_level {
return Err(Error::Forbidden);
}
// Verify the wait time is not reduced below the original
if data.wait_time < emergency_access.wait_time {
return Err(Error::Forbidden);
}
// Apply only allowed changes
emergency_access.wait_time = data.wait_time;
emergency_access.save(&conn).await?;
Ok(Json(json!({ "success": true })))
}
Exploitation & Lab Setup
Red Team
Prerequisites:
- A Vaultwarden instance (version 1.30.3) with at least two users: a victim (grantor) and an attacker (grantee).
- The grantor must have granted emergency access to the attacker with read-only access and a non-zero wait time.
Exploitation Steps:
Identify the Emergency Access ID: The attacker needs the ID of the emergency access grant. This can be obtained from the
/api/emergency-accessendpoint after authentication.Craft the Malicious Request: Send a PUT request to
/api/emergency-access/{id}/updatewith the following JSON payload:{ "access_level": "full", "wait_time": 0 }Execute the Request:
curl -X PUT \ -H "Authorization: Bearer <attacker_token>" \ -H "Content-Type: application/json" \ -d '{"access_level":"full","wait_time":0}' \ https://vaultwarden.example.com/api/emergency-access/<emergency_access_id>/updateAccess the Vault: The attacker can now immediately access the victim's vault with full control using the emergency access feature.
Blue Team
Detection:
- Monitor API logs for unusual PUT requests to
/api/emergency-access/{id}/updatewhere theaccess_levelorwait_timeparameters are changed. - Alert on any emergency access grant that is activated immediately (wait_time = 0) or where the access level is changed from read to full.
Hunting:
- Search for emergency access grants where the
access_levelis "full" and thewait_timeis less than the original value set by the grantor. - Correlate emergency access activations with the grantee's IP address and user agent.
Prevention:
- Implement network segmentation to limit access to the Vaultwarden API.
- Use Web Application Firewall (WAF) rules to block requests that modify emergency access parameters in an unauthorized manner.
Indicators of Compromise (IOCs)
Network IOCs:
- PUT requests to
/api/emergency-access/{id}/updatewith JSON body containing"access_level": "full"and"wait_time": 0. - Unusual API calls from a grantee's IP address immediately after being granted emergency access.
- PUT requests to
System IOCs:
- Vaultwarden logs showing emergency access activation with
wait_timeof 0. - Emergency access grants where the
access_levelhas been changed from "read" to "full" without the grantor's knowledge.
- Vaultwarden logs showing emergency access activation with
File IOCs:
- Modified database entries in the
emergency_accesstable whereaccess_levelis "full" andwait_timeis 0.
- Modified database entries in the
Detection Engineering
YARA Rule
rule CVE_2024_39924_Emergency_Access_Escalation {
meta:
description = "Detects Vaultwarden emergency access privilege escalation attempts"
author = "Valters IT"
date = "2024-01-01"
reference = "CVE-2024-39924"
strings:
$json_payload = /"access_level"\s*:\s*"full"/ nocase
$json_wait = /"wait_time"\s*:\s*0/ nocase
$api_endpoint = "/api/emergency-access/"
condition:
$api_endpoint and $json_payload and $json_wait
}
Sigma Rule
title: Vaultwarden Emergency Access Privilege Escalation
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects attempts to exploit CVE-2024-39924 by modifying emergency access metadata
author: Valters IT
date: 2024/01/01
logsource:
category: webserver
product: vaultwarden
detection:
selection:
http.method: 'PUT'
http.url|contains: '/api/emergency-access/'
http.request_body|contains:
- '"access_level":"full"'
- '"wait_time":0'
condition: selection
falsepositives:
- Legitimate emergency access configuration changes (rare)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-39924 Vaultwarden Emergency Access Escalation"; flow:to_server; http.method; content:"PUT"; http.uri; content:"/api/emergency-access/"; http.request_body; content:"\"access_level\":\"full\""; content:"\"wait_time\":0"; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable Emergency Access: If the feature is not critical, disable it in the Vaultwarden admin panel until a patch is available.
- Audit Existing Grants: Review all current emergency access grants. Revoke any that are not strictly necessary.
- Monitor Logs: Actively monitor Vaultwarden logs for any suspicious emergency access activity.
Long-Term Fixes:
- Apply Official Patch: Once Vaultwarden releases a patched version (e.g., 1.30.4 or later), upgrade immediately.
- Implement Workaround: If patching is not possible, consider implementing a reverse proxy (e.g., Nginx) with custom rules to block PUT requests to the emergency access endpoint that contain unauthorized parameter changes.
- Network Segmentation: Place Vaultwarden behind a VPN or firewall to restrict access to trusted users only.
Valters IT Signature
This report was generated by Valters IT DevSecOps AI. For questions, contact security@valters.it.