HIGH replay attackactixhmac signatures

Replay Attack in Actix with Hmac Signatures

Replay Attack in Actix with Hmac Signatures — how this specific combination creates or exposes the vulnerability

A replay attack occurs when an adversary intercepts a valid request and retransmits it to reproduce the intended effect without going through the authentication logic. In Actix-based services that rely on Hmac Signatures for request integrity, a common pattern is to sign a canonical string that includes a timestamp and a nonce. If the server only validates the Hmac correctly but does not enforce strict freshness constraints on the timestamp and does not enforce global nonce uniqueness, an attacker can capture a legitimately signed request and replay it later. The signature remains valid because the Hmac over the same canonical data and shared secret does not change, and the server may accept the request as long as the timestamp is within a loosely configured window.

Actix web applications often implement Hmac Signatures by concatenating a timestamp, a nonce, and the request payload, then computing a SHA-256 Hmac with a shared secret. The server then recomputes the Hmac and compares it in constant time. The vulnerability arises when the implementation treats a matching Hmac as sufficient proof of authenticity without ensuring that the same timestamp-nonce combination has not been seen recently. For example, if the server accepts timestamps with a generous skew window (e.g., five minutes) and does not track previously used nonces, an attacker can record a request signed at time T and replay it within that window. Because the server will accept T as fresh, the request is processed as intended by the original sender, potentially leading to duplicate transactions, unauthorized state changes, or privilege escalation.

Real-world impacts include unauthorized fund transfers, repeated API calls that consume resources, and circumvention of rate-limiting mechanisms. This pattern is especially problematic when the Hmac scheme does not incorporate a server-side nonce or when the server’s nonce cache is too small or improperly invalidated. Even with proper timestamp validation, an attacker can exploit weak entropy in nonce generation or predictable nonce values to mount replay attempts. Because Actix middleware typically validates signatures early in the request pipeline, a replayed request may proceed to business logic handlers before being rejected, amplifying the risk.

Hmac Signatures-Specific Remediation in Actix — concrete code fixes

To mitigate replay attacks in Actix when using Hmac Signatures, you must enforce timestamp freshness with a tight tolerance and maintain a server-side cache of recently used nonces. Below are concrete, realistic code examples that demonstrate a secure approach using Actix web and the hmac and sha2 crates.

First, define your shared secret and a structure for validated claims:

use hmac::{Hmac, Mac};
use sha2::Sha256;
use std::collections::HashSet;
use std::sync::{Arc, Mutex};
use std::time::{SystemTime, UNIX_EPOCH};

type HmacSha256 = Hmac<Sha256>;

struct NonceCache {
seen: HashSet<String>,
}

struct AppState {
mac_key: Vec<u8>,
nonces: Arc<Mutex<NonceCache>>,
timestamp_window_secs: u64,
}

Next, implement request validation that checks both timestamp and nonce uniqueness. This handler demonstrates how to parse headers, verify the Hmac, and reject replays:

use actix_web::{web, HttpRequest, HttpResponse, Error};
use serde::Deserialize;

#[derive(Deserialize)]
struct SignedRequest {
timestamp: u64,
nonce: String,
payload: String,
signature: String,
}

async fn handle_signed_request(
req: HttpRequest,
body: web::Json<SignedRequest>,
data: web::Data<Arc<AppState>>,
) -> Result<HttpResponse, Error> {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs();

// 1) Check timestamp freshness
if data.timestamp_window_secs == 0 {
return Ok(HttpResponse::BadRequest().body("clock skew not allowed"));
}
if (body.timestamp as i64 - now as i64).abs() > data.timestamp_window_secs as i64 {
return Ok(HttpResponse::Unauthorized().body("timestamp outside tolerance"));
}

// 2) Ensure nonce has not been used recently
let mut nonces = data.nonces.lock().unwrap();
if nonces.seen.contains(&body.nonce) {
return Ok(HttpResponse::Unauthorized().body("replay detected: nonce used"));
}
nonces.seen.insert(body.nonce.clone());

// 3) Recompute Hmac and verify
let mut mac = HmacSha256::new_from_slice(&data.mac_key)
.map_err(|_| actix_web::error::ErrorInternalServerError("hmac init failed"))?;
let canonical = format!(

Hmac Signatures-Specific Remediation in Actix — concrete code fixes (continued)

Below is the continuation of the secure Actix handler and supporting logic to prevent replay attacks. This includes constant-time comparison and a background cleanup task to bound the nonce cache size.

        &body.timestamp,
&body.nonce,
&body.payload,
);
let computed_sig = hex::encode(mac.finalize().into_bytes());

// 4) Constant-time comparison to avoid timing leaks
if !hmac::crypto_mac::Output::verify_slice(
&computed_sig.into_bytes(),
&body.signature.into_bytes(),
) {
return Ok(HttpResponse::Unauthorized().body("invalid signature"));
};

// Business logic follows only after validation
Ok(HttpResponse::Ok().body(format!("processed: {}", body.payload)))
}

// Optional: periodically prune old nonces to prevent unbounded growth
async fn prune_nonces(nonces: Arc<Mutex<NonceCache>>) {
// In production, use a time-based eviction strategy appropriate to your window size
// For simplicity, this example shows a basic retain pattern that would be scheduled externally
}

Key points in this remediation:

  • Use a tight timestamp_window_secs (e.g., 30–60 seconds) to limit the window in which a captured request remains valid.
  • Maintain a server-side nonce cache and reject any nonce seen within the operational lifetime of the service. For long-running processes, implement eviction based on time or cache size.
  • Always perform Hmac verification using a constant-time comparison to prevent timing side channels.
  • Ensure nonces have sufficient entropy (e.g., cryptographically random strings) and are not predictable.

By combining timestamp validation with nonce replay tracking, you ensure that even if an attacker captures a correctly signed request, they cannot reuse it beyond the allowed freshness window or with a repeated nonce.

Frequently Asked Questions

Why is a nonce cache necessary if timestamps are already checked in Actix Hmac replay protection?
Timestamps alone cannot prevent replays within the allowed time window. A nonce cache ensures each signed request is used only once, blocking replay attempts even when timestamps are within tolerance.
Can I rely solely on short timestamp windows instead of maintaining a nonce cache in Actix?
Short windows reduce the replay window but do not eliminate risk; clock skew, synchronization issues, and attacks within the window remain. A nonce cache provides stronger guarantees by preventing duplicate nonces regardless of timing.