Replay Attack in Actix with Basic Auth
Replay Attack in Actix with Basic Auth — how this specific combination creates or exposes the vulnerability
A replay attack occurs when an attacker intercepts a valid request and retransmits it to reproduce the original effect. In Actix applications that rely solely on HTTP Basic Authentication, this risk is pronounced because the authentication material (username and password) is reused in every request without additional anti-replay controls. With Basic Auth, credentials are base64-encoded but not encrypted; if transmitted over a non-encrypted channel they are trivially recoverable, and even over TLS, the static nature of the credentials makes them susceptible to replay.
Consider an Actix web service that accepts a username and password via the Authorization header. Once authenticated, the service may issue a session-like token or rely on the connection’s TLS session for subsequent requests. However, if the service does not incorporate a per-request nonce, timestamp, or other dynamic value, an attacker who captures a legitimate request can simply replay it—potentially using the same TCP or TLS session—and the server will accept it as valid. This is especially dangerous for operations that change state (e.g., transferring funds or modifying configuration), where the idempotency of the request makes replay hard to detect.
In a black-box scan, middleBrick’s BOLA/IDOR and Authentication checks can surface endpoints that accept static Basic Auth credentials without additional freshness guarantees. Because middleBrick tests unauthenticated attack surfaces, it can detect whether responses differ when the same Authorization header is reused across multiple requests, flagging the absence of replay resistance. The scanner also examines whether the API leverages TLS correctly and whether sensitive data exposure occurs when credentials are transmitted, aligning with checks such as Data Exposure and Encryption.
For LLM-specific concerns, middleBrick’s LLM/AI Security checks include system prompt leakage detection and active prompt injection testing. While these are not directly tied to Basic Auth replay, they underscore the broader principle that static or poorly protected endpoints may leak sensitive context. An endpoint that echoes errors or exposes stack traces might inadvertently reveal whether authentication succeeded, aiding an attacker in refining a replay attempt. Unauthenticated LLM endpoint detection further ensures that any AI-related endpoints do not become an unintended channel for credential exposure.
Because middleBrick performs no internal fixes, its findings include remediation guidance. Developers should treat replay as a design constraint and augment Basic Auth with mechanisms that guarantee request uniqueness. The guidance provided by middleBrick helps prioritize such controls by mapping findings to standards like OWASP API Top 10 and PCI-DSS, ensuring that replay risk is addressed as part of a comprehensive API security posture.
Basic Auth-Specific Remediation in Actix — concrete code fixes
To mitigate replay in Actix when using HTTP Basic Auth, introduce per-request uniqueness via nonces or timestamps, enforce short-lived credentials, and prefer token-based authentication where feasible. Below are concrete Actix examples that demonstrate a more secure approach.
Example 1: Basic Auth with timestamp and nonce validation
This handler verifies that each request includes an X-Auth-Timestamp and X-Auth-Nonce header, ensuring freshness and uniqueness. The server maintains a short-lived cache of recently seen nonces to reject replays.
use actix_web::{web, HttpRequest, HttpResponse, Responder};
use std::collections::HashSet;
use std::sync::{Arc, Mutex};
use std::time::{SystemTime, UNIX_EPOCH};
struct AuthState {
seen_nonces: Mutex>,
nonce_ttl_secs: u64,
}
async fn protected_route(
req: HttpRequest,
body: web::Bytes,
data: web::Data>,
) -> impl Responder {
let auth_header = match req.headers().get("Authorization") {
Some(h) => h.to_str().unwrap_or(""),
None => return HttpResponse::Unauthorized().body("Missing Authorization"),
};
// Basic Auth format: "Basic base64(credentials)"
let token = auth_header.strip_prefix("Basic ").unwrap_or("");
let credentials = match base64::decode(token) {
Ok(c) => String::from_utf8_lossy(&c).to_string(),
Err(_) => return HttpResponse::Unauthorized().body("Invalid credentials"),
};
let parts: Vec<&str> = credentials.split(':').collect();
if parts.len() != 2 {
return HttpResponse::Unauthorized().body("Invalid credentials format");
}
let (username, password) = (parts[0], parts[1]);
// Validate username/password against your backend (e.g., database)
if !valid_user_pass(username, password).await {
return HttpResponse::Unauthorized().body("Invalid user or password");
}
// Replay protection
let timestamp = match req.headers().get("X-Auth-Timestamp") {
Some(t) => t.to_str().unwrap_or(""),
None => return HttpResponse::BadRequest().body("Missing timestamp"),
};
let nonce = match req.headers().get("X-Auth-Nonce") {
Some(n) => n.to_str().unwrap_or(""),
None => return HttpResponse::BadRequest().body("Missing nonce"),
};
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
let ts: u64 = match timestamp.parse() {
Ok(v) => v,
Err(_) => return HttpResponse::BadRequest().body("Invalid timestamp"),
};
if now.saturating_sub(ts) > data.nonce_ttl_secs {
return HttpResponse::BadRequest().body("Timestamp expired");
}
let mut seen = data.seen_nonces.lock().unwrap();
if seen.contains(nonce) {
return HttpResponse::BadRequest().body("Replay detected");
}
seen.insert(nonce.to_string());
HttpResponse::Ok().body(format!("Authenticated as {}", username))
}
async fn valid_user_pass(username: &str, password: &str) -> bool {
// Replace with secure credential verification
username == "alice" && password == "s3cret"
}
Example 2: MiddleBrick integrations for ongoing monitoring
Use the middleBrick CLI to validate that your endpoints include replay-resistant headers and that responses do not leak authentication state. Run middlebrick scan <url> to obtain a security risk score and findings. If you need continuous assurance, the Pro plan provides continuous monitoring and can integrate with your CI/CD pipeline via the GitHub Action, failing builds if the security score drops below your chosen threshold.
For development workflows tightly coupled with AI tools, the MCP Server allows you to scan APIs directly from your AI coding assistant, embedding security checks into your edit loop without leaving your IDE.