Auth Bypass in Actix with Hmac Signatures
Auth Bypass in Actix with Hmac Signatures — how this specific combination creates or exposes the vulnerability
In Actix-based services, an authentication bypass can occur when Hmac signatures are generated or verified in a way that does not protect the canonical representation of the request. For example, if the server signs only a subset of the request data—such as the raw query string while omitting certain headers, or signing a JSON body after non-deterministic key ordering—the resulting signature becomes context-dependent. An attacker can change the request in ways that do not affect the signature verification path, leading to authentication bypass. middleBrick detects this pattern during unauthenticated scans by comparing the runtime request/response behavior against the expected integrity scope defined in the OpenAPI specification.
A concrete scenario involves an endpoint that accepts both an Hmac signature in a custom header and a timestamp to prevent replay. If the server does not include the HTTP method and the full path in the signed string, an attacker can reuse a valid signature by changing the HTTP verb or path segment in a way that the server still routes to the same handler. This is especially risky when the server normalizes paths inconsistently (e.g., treating /api/v1/resource and /api/v1/resource/ as equivalent) but only normalizes before signing. middleBrick’s BOLA/IDOR and Authentication checks surface these inconsistencies by observing whether different unauthenticated requests produce the same or different risk scores.
Another common pattern in Actix applications is conditional signature inclusion, where a developer accidentally skips signing for certain routes assumed to be internal or read-only. If such routes expose sensitive data or trigger state changes, an attacker can exploit the missing signature requirement to perform authenticated actions without possessing valid credentials. Because these routes may not be explicitly documented in the API spec, they often remain unchecked until an automated scan validates the coverage of the signature scheme across the surface area. middleBrick’s OpenAPI/Swagger analysis resolves all $ref definitions and cross-references them with runtime checks to ensure every operation that should be protected is included in the Hmac verification logic.
The LLM/AI Security module further examines whether prompts or model outputs inadvertently disclose information about the signing process, such as verbose error messages that reveal which components were or were not signed. System prompt leakage patterns can indicate whether the backend embeds signature metadata in responses, which may aid an attacker in refining bypass techniques. By combining these checks, middleBrick provides a comprehensive view of how Hmac-based authentication can be unintentionally weakened in Actix services.
Hmac Signatures-Specific Remediation in Actix — concrete code fixes
To remediate Hmac signature issues in Actix, ensure that the canonical string used for signing includes the HTTP method, the full normalized path, selected headers, and the request body in a deterministic form. Below are concrete, working examples that demonstrate a secure approach using the hmac and sha2 crates.
use actix_web::{dev::ServiceRequest, Error, HttpMessage};
use hmac::{Hmac, Mac};
use sha2::Sha256;
use std::collections::BTreeMap;
type HmacSha256 = Hmac<Sha256>;
fn build_canonical_string(req: &ServiceRequest) -> String {
let method = req.method().as_str();
let path = req.path().to_string();
// Deterministic header selection: include only security-relevant headers
let headers = vec![("content-type", req.headers().get("content-type").and_then(|v| v.to_str().ok()))];
let body = req
.get_payload()
.and_then(|b| std::str::from_utf8(b).ok())
.unwrap_or("");
// Use a stable ordering for any included parameters; here we show a simple example
format!("{}|{}|{}|{}", method, path, headers.iter().map(|(k, v)| format!("{}:{}", k, v.unwrap_or(""))).collect::<Vec<String>>().join("&"), body)
}
async fn sign_request(req: ServiceRequest, secret: &[u8]) -> Result<ServiceRequest, Error> {
let canonical = build_canonical_string(&req);
let mut mac = HmacSha256::new_from_slice(secret).expect("HMAC can take key of any size");
mac.update(canonical.as_bytes());
let result = mac.finalize();
let signature = hex::encode(result.into_bytes());
req.extensions_mut().insert(signature);
Ok(req)
}
async fn verify_request(req: ServiceRequest, secret: &[u8]) -> Result<ServiceRequest, Error> {
let canonical = build_canonical_string(&req);
let provided = req.headers().get("x-api-signature").and_then(|v| v.to_str().ok()).ok_or_else(|| actix_web::error::ErrorUnauthorized("missing signature"))?;
let mut mac = HmacSha256::new_from_slice(secret).expect("HMAC can take key of any size");
mac.update(canonical.as_bytes());
mac.verify_slice(provided.as_ref()).map_err(|_| actix_web::error::ErrorUnauthorized("invalid signature"))?;
Ok(req)
}
These snippets ensure that the canonical string is constructed consistently on both the client and server, including the exact HTTP method and path as used in the request line. Using a sorted structure such as BTreeMap for any included query or header parameters guarantees deterministic ordering, which is critical for signature stability. The verification step must apply the same normalization and selection rules; any deviation can allow an attacker to manipulate elements that are excluded from the signature.
Additionally, always include a nonce or timestamp within the signed string and enforce replay protection on the server side to prevent reused signatures. The examples above keep the timestamp and nonce handling implicit to focus on the canonical construction; in production, you should explicitly add and validate these values. middleBrick’s CLI can validate that your endpoints enforce signature verification for all intended operations by running middlebrick scan <url> and reviewing the Authentication and BOLA/IDOR findings.
For teams using the Pro plan, continuous monitoring can alert you when new endpoints are introduced that do not include the required signature validation, and the GitHub Action can fail builds if a scan detects missing coverage. The MCP Server allows you to trigger scans directly from your development environment, helping catch inconsistencies before deployment. These integrations complement the code-level fixes by ensuring that remediation remains enforced across the lifecycle of the service.
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 |