Broken Authentication in Rocket with Hmac Signatures
Broken Authentication in Rocket with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Rocket is a web framework for Rust, and using Hmac Signatures for request authentication is common when building APIs that require integrity and authenticity guarantees. However, incorrect implementation can lead to Broken Authentication, allowing an attacker to bypass or forge authentication. This occurs when the Hmac signature is computed over insufficient data, is transmitted or stored insecurely, or when key management practices are weak.
Consider a typical Hmac flow: the client creates a canonical string to sign (often including a timestamp, nonce, and payload), computes Hmac using a shared secret, and sends the signature in a header. If the server does not enforce strict validation—such as verifying the timestamp window, checking for replayed nonces, or ensuring the signature covers all required components—an attacker can reuse intercepted signatures or manipulate parameters to authenticate as another user.
In Rocket, a vulnerability can arise if the signature is computed only over the request body or only over selected headers, omitting critical context such as the HTTP method, path, or a per-request nonce. An attacker could then change the method or path while keeping the signature valid, leading to privilege escalation or unauthorized actions. Additionally, if the shared secret is embedded in client-side code or transmitted alongside the signature, it can be extracted and misused.
Another common pitfall is the lack of replay protection. Without a nonce or timestamp with a short validity window, an intercepted signed request can be replayed to perform actions on behalf of the authenticated user. Rocket routes that rely solely on Hmac signatures without these safeguards expose a Broken Authentication vector aligned with OWASP API Top 10 API1:2023 Broken Object Level Authorization (BOLA) and API2:2023 Broken Authentication.
Runtime scanning with middleBrick can detect these issues by analyzing the OpenAPI specification and correlating it with observed behavior. For example, if the spec defines security schemes using Hmac but does not require inclusion of the HTTP method or path in the signed string, or if the runtime tests show that modified requests with altered paths still succeed, middleBrick reports a high-severity finding. The scanner also checks whether the signature mechanism leaks secrets through error messages or inconsistent timing, which can aid attackers in offline brute-force attacks.
To illustrate a correct implementation, the following example shows a Rocket route where the Hmac signature is computed over the method, path, timestamp, nonce, and body, and validated with constant-time comparison. This reduces the risk of Broken Authentication by ensuring that any change to the signed context invalidates the signature.
Hmac Signatures-Specific Remediation in Rocket — concrete code fixes
Remediation focuses on ensuring the Hmac signature covers all relevant request components, enforcing short-lived nonces or timestamps, and using secure comparison to prevent timing attacks. Below is a concrete example of a Rocket route that implements robust Hmac authentication.
use rocket::{get, http::Status, request::Request, response::Responder, State};
use rocket::serde::json::Json;
use hmac::{Hmac, Mac};
use sha2::Sha256;
type HmacSha256 = Hmac;
const TIMESTAMP_TOLERANCE_SECS: i64 = 300; // 5 minutes
#[get("/resource<id>")]
fn get_resource(
id: u64,
request: &Request<'_>,
key: &State<[u8; 32]>,
) -> Result<Json<String>, (Status, String)> {
let headers = request.headers();
let signature_header = headers.get_one("X-Api-Signature")
.ok_or((Status::Unauthorized, "Missing signature".to_string()))?;
let timestamp = headers.get_one("X-Api-Timestamp")
.ok_or((Status::Unauthorized, "Missing timestamp".to_string()))?;
let nonce = headers.get_one("X-Api-Nonce")
.ok_or((Status::Unauthorized, "Missing nonce".to_string()))?;
let timestamp_secs: i64 = timestamp.parse().map_err(|_| (Status::BadRequest, "Invalid timestamp".to_string()))?;
let now = chrono::Utc::now().timestamp();
if (now - timestamp_secs).abs() > TIMESTAMP_TOLERANCE_SECS {
return Err((Status::Unauthorized, "Timestamp outside tolerance".to_string()));
}
// Build the string to verify, exactly as the client did:
// method|path|timestamp|nonce|body
let body = request.body().map(|b| std::str::from_utf8(b).unwrap_or("")).unwrap_or("");
let string_to_verify = format!( "{}|{}|{}|{}|{}", request.method(), request.uri().path(), timestamp, nonce, body);
let mut mac = HmacSha256::new_from_slice(&key)
.map_err(|_| (Status::InternalServerError, "Hmac setup error".to_string()))?;
mac.update(string_to_verify.as_bytes());
let computed_signature = mac.finalize().into_bytes();
// Decode client signature (hex or base64 as agreed)
let client_signature = hex::decode(signature_header)
.map_err(|_| (Status::BadRequest, "Invalid signature encoding".to_string()))?;
// Constant-time comparison to avoid timing attacks
use subtle::ConstantTimeEq;
let computed_ct = subtle::CtOption::new(computed_signature, (computed_signature.len() == client_signature.len()).into());
let client_ct = subtle::CtOption::new(client_signature, (computed_signature.len() == client_signature.len()).into());
if computed_ct.ct_eq(&client_ct).into() {
Ok(Json(format!(\"Access granted for id: {}\", id)))
} else {
Err((Status::Unauthorized, "Invalid signature".to_string()))
}
}
This example ensures the signature includes method, path, timestamp, nonce, and body, mitigating tampering and replay risks. The timestamp window and nonce prevent replay attacks, and constant-time comparison avoids timing-based extraction. Using a strong key stored securely (e.g., via Rocket managed state or environment variables) is essential. middleBrick can validate that your API’s security scheme enforces such practices across endpoints and aligns the findings with frameworks like OWASP API Top 10.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |