Padding Oracle in Actix with Hmac Signatures
Padding Oracle in Actix with Hmac Signatures — how this specific combination creates or exposes the vulnerability
A padding oracle in an Actix-web service that uses Hmac Signatures typically arises when the application processes encrypted request payloads (for example, JWTs or custom encrypted API messages) and reveals distinct error behavior based on padding validity. In such setups, the server first validates an Hmac signature to ensure integrity, then decrypts the payload. If decryption or unpadding produces a detectable error, and the server responds differently to malformed padding versus other decryption failures, an attacker can iteratively submit manipulated ciphertexts and observe timing or status differences to gradually recover plaintext without knowing the key.
Consider an Actix handler that expects an encrypted body and an X-API-Signature header containing an Hmac of the ciphertext. The handler verifies the Hmac, decrypts using AES in CBC mode, and then removes PKCS7 padding. A typical vulnerable flow is:
- The client sends a ciphertext
cand an Hmac computed overc. - If the Hmac is invalid, the server returns a 401 with a generic message.
- If the Hmac is valid but decryption fails due to bad padding, the server returns a 400 with a message like “invalid padding”, whereas other decryption errors return 400 with “decryption failed”.
This distinguishable response allows an attacker to treat the server as a padding oracle. By modifying bytes in c and observing which responses indicate padding errors, the attacker can recover the plaintext block by block. In the context of API security checks run by middleBrick, such behavioral differences would be flagged under Input Validation and Authentication checks, because the server should not leak the reason for failure and should treat all invalid inputs uniformly.
Real-world impact aligns with the OWASP API Top 10 “Broken Object Level Authorization” and “Security Misconfiguration” when APIs inadvertently expose cryptographic error details. For example, a crafted ciphertext with a modified last block can allow an attacker who can distinguish padding errors to decrypt sensitive data, such as tokens or PII, without the Hmac key. middleBrick scans test these unauthenticated attack surfaces and would surface findings related to inconsistent error handling and missing integrity checks around encrypted payloads.
Hmac Signatures-Specific Remediation in Actix — concrete code fixes
Remediation focuses on ensuring that Hmac verification and decryption fail safely and uniformly, without exposing operational details. The key principle is to make all error paths indistinguishable in timing and response body, and to validate integrity before attempting decryption.
1. Constant-time Hmac verification and unified error handling
Always verify the Hmac over the entire request payload using a constant-time comparison to avoid timing leaks. In Actix, extract the signature, compute Hmac with the shared secret, and compare the result in constant time. Return a generic error for any validation failure.
use hmac::{Hmac, Mac};
use sha2::Sha256;
use actix_web::{web, HttpResponse, Error};
type HmacSha256 = Hmac<Sha256>;
fn verify_hmac(body: &[u8], received_sig: &str, secret: &[u8]) -> bool {
let mut mac = HmacSha256::new_from_slice(secret).expect("Hmac can take key of any size");
mac.update(body);
// Use constant_time_eq to avoid timing leaks
match received_sig.parse::<GenericArray<u8, U32>>() {
Ok(sig) => mac.verify_slice(&sig).is_ok(),
Err(_) => false,
}
}
async fn handle_secure(headers: web::Header<actix_web::http::header::Authorization>, body: web::Bytes) -> Result<HttpResponse, Error> {
let secret = include_bytes!("./hmac_secret.key");
let auth = headers.into_inner();
let received_sig = auth.as_str().trim_start_matches("Hmac ");
// Constant-time verification; on failure return generic error
if !verify_hmac(&body, received_sig, secret) {
return Ok(HttpResponse::Unauthorized().json(serde_json::json!({
"error": "invalid_request"
})));
}
// Proceed to decrypt and parse; any decryption/padding failure also returns the same generic error
match decrypt_payload(&body) {
Ok(payload) => Ok(HttpResponse::Ok().json(payload)),
Err(_) => Ok(HttpResponse::Unauthorized().json(serde_json::json!({
"error": "invalid_request"
}))),
}
}
2. Encrypt-then-Mac and safe decryption with uniform errors
Adopt an encrypt-then-Mac approach: Hmac the ciphertext, not the plaintext. This ensures integrity before decryption and avoids issues with malleable plaintext. When decrypting, use authenticated encryption (e.g., AES-GCM) where possible; if using AES-CBC, ensure Hmac covers the ciphertext and verify the Hmac before CBC decryption. Always catch padding errors and map them to the same generic response as other failures.
use aes_gcm::{Aes256Gcm, KeyInit, aead::{Aead, OsRng, generic_array::GenericArray}};
use hmac::{Hmac, Mac};
use sha2::Sha256;
use actix_web::web;
// Example: decrypt after verifying Hmac over ciphertext
fn decrypt_payload(ciphertext: &[u8], hmac_sig: &str, secret_key: &[u8]) -> Result<Vec<u8>, &'static str> {
// Verify Hmac first (constant-time compare inside verify_hmac)
if !verify_hmac(ciphertext, hmac_sig, secret_key) {
return Err("invalid_request");
}
// If using AES-GCM, the tag is typically appended or transmitted separately;
// here we assume ciphertext includes nonce and tag as required by the protocol.
let key = GenericArray::from_slice(secret_key); // secret_key must be 32 bytes for AES256
let cipher = Aes256Gcm::new(key);
// For CBC+Hmac, perform CBC decryption after Hmac verification, then remove PKCS7 padding
// within a function that catches padding errors and returns a generic failure.
unimplemented!("Implement AES-GCM or CBC+PKCS7 with constant-time unpadding and uniform errors")
}
3. Ensure server-side configuration does not aid oracle behavior
Do not differentiate error codes or messages for padding failures versus other cryptographic errors. Combine logging (with care to avoid logging sensitive data) with generic user-facing responses. middleBrick’s checks for Input Validation and Authentication would highlight inconsistent error handling; remediation aligns with producing uniform responses and robust Hmac usage.