Request Smuggling in Actix with Hmac Signatures
Request Smuggling in Actix with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Request smuggling occurs when an intermediary (such as a load balancer or reverse proxy) and the backend server disagree on how to parse the boundaries of an HTTP request. In Actix applications that use HMAC signatures for request authentication, the risk is amplified when the signature covers only a subset of the message or when the body is processed inconsistently between the proxy and the application.
Consider an Actix service that validates a request body only after the HMAC signature is verified. If a front-end proxy normalizes or splits the incoming request differently than Actix, the body received by the application may differ from what the proxy validated. For example, a client may send Transfer-Encoding: chunked while maintaining a Content-Length header, or use differing whitespace or line endings. If the HMAC is computed over the original body bytes as seen by the client, but Actix computes it over a transformed body, the signatures may still match while the parsed body content diverges. This mismatch can allow a request to be interpreted as two separate requests by the proxy and Actix, enabling request smuggling attacks such as request splitting or request concatenation.
In the context of the 12 security checks run by middleBrick, this pattern falls under BFLA/Privilege Escalation and Input Validation. An attacker may smuggle a request that causes the server to process an unintended administrative action or bypass intended authorization boundaries. middleBrick’s unauthenticated scan can surface inconsistencies between documented behavior and runtime parsing by detecting unexpected status code variations or response differences that indicate parsing divergence. Since middleBrick compares spec definitions containing HMAC-related headers and body constraints with runtime findings, it can highlight mismatches between expected and observed body handling in Actix endpoints that use HMAC signatures.
A realistic example is an Actix endpoint that expects a JSON body signed with an HMAC in the X-API-Signature header. If the proxy preserves chunked encoding while Actix parses the body as a stream, an attacker can craft a request where the first logical request is benign and the second request is malicious. Because the HMAC may only cover the first chunk, Actix could accept the second request as valid if it does not recompute or re-validate the signature on the combined body. middleBrick’s detection of SSRF and Data Exposure findings can indicate whether downstream behavior inadvertently exposes internal endpoints when smuggling attempts succeed.
Hmac Signatures-Specific Remediation in Actix — concrete code fixes
To mitigate request smuggling in Actix when using HMAC signatures, ensure that body parsing and signature verification are performed on a canonical, normalized representation of the request. This prevents discrepancies between what the proxy and the application see. Below are concrete code examples for Actix in Rust that demonstrate secure handling of HMAC-signed requests.
First, always read and buffer the entire body before computing the HMAC. Avoid streaming verification that processes partial body content. Use Actix’s payload configuration to limit maximum body size and enforce strict content-length checks.
use actix_web::{web, App, HttpServer, HttpRequest, HttpResponse, Error};
use actix_web::http::header::HeaderValue;
use hmac::{Hmac, Mac};
use sha2::Sha256;
type HmacSha256 = Hmac<Sha256>;
async fn verify_hmac(
req: &HttpRequest,
body: &[u8],
secret: &str,
) -> Result<(), HttpResponse> {
let signature_header = req.headers().get("X-API-Signature")
.ok_or_else(|| HttpResponse::BadRequest().body("Missing signature"))?;
let signature = signature_header.to_str().map_err(|_| {
HttpResponse::BadRequest().body("Invalid signature header")
})?;
let mut mac = HmacSha256::new_from_slice(secret.as_bytes())
.map_err(|_| HttpResponse::InternalServerError().body("HMAC init error"))?;
mac.update(body);
let computed = mac.finalize();
let code = computed.into_bytes();
// Use constant-time comparison
use subtle::ConstantTimeEq;
let received = hex::decode(signature).map_err(|_| {
HttpResponse::BadRequest().body("Invalid signature encoding")
})?;
if code.ct_eq(&received).into() {
Ok(())
} else {
Err(HttpResponse::Unauthorized().body("Invalid signature"))
}
}
async fn handler(
req: HttpRequest,
payload: web::Payload,
) -> Result<HttpResponse, Error> {
let body = web::block(move || {
let bytes = actix_web::web::Bytes::from_request(&req, payload).into_inner()?;
Ok::<_, actix_web::Error>(bytes)
})
.await??;
const SECRET: &str = "super-secret-key";
verify_hmac(&req, &body, SECRET)?;
// Process the verified body
Ok(HttpResponse::Ok().body("OK"))
}
Second, enforce strict header and body consistency. If your API relies on Content-Length or Transfer-Encoding, ensure that Actix rejects requests where these headers conflict. Configure the server to normalize incoming requests before routing them to handlers that perform HMAC verification.
Third, align your HMAC scope with the security boundaries defined in your OpenAPI specification. If your spec defines that the signature covers a specific subset of headers or the entire request including certain metadata, reflect that scope exactly in your verification logic. middleBrick’s OpenAPI/Swagger spec analysis can help verify that your implementation matches the documented contract, especially when $ref definitions are used to describe security schemes.
Finally, test these patterns using middleBrick’s CLI to scan your endpoints and confirm that no smuggling-related Input Validation or BFLA findings appear. The combination of canonical body handling, strict header validation, and aligned HMAC scope significantly reduces the risk of request smuggling in Actix services that depend on HMAC signatures.