HIGH replay attackaxum

Replay Attack in Axum

How Replay Attack Manifests in Axum

Replay attacks in Axum-based APIs occur when an attacker captures a legitimate, authenticated request and retransmits it to achieve an unintended effect—such as duplicate financial transactions or unauthorized state changes. Axum, built on hyper and tower, does not include built-in replay protection for state-changing endpoints (e.g., POST, PUT, DELETE). The vulnerability typically arises in two patterns:

  • Missing Nonce Validation: APIs using stateless authentication (e.g., JWT) often omit a unique, single-use token (jti claim) or timestamp check. An attacker can replay the same JWT and request body indefinitely. In Axum, this commonly appears in handlers that extract authentication via Extension<AuthUser> or TypedHeader<Authorization> without validating request uniqueness.
  • Idempotency Key Misuse: While Axum does not enforce idempotency, APIs that accept Idempotency-Key headers but fail to store and check them against replays are vulnerable. A typical Axum handler might process a payment request without verifying whether the same key was already used.

Consider this vulnerable Axum endpoint that processes fund transfers using a JWT extracted from the Authorization header but without any replay safeguards:

use axum::{extract::Json, routing::post, Router, http::StatusCode};
use serde::{Deserialize, Serialize};

#[derive(Deserialize)]
struct TransferRequest {
from: String,
to: String,
amount: u32,
}

async fn transfer_funds(
user: axum::extract::Extension<AuthUser>,
Json(payload): Json<TransferRequest>,
) -> Result<StatusCode, StatusCode> {
// Vulnerable: no nonce or idempotency check
process_transfer(&user.id, &payload.from, &payload.to, payload.amount)
.await
.then(|_| Ok(()))
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)
}

An attacker who intercepts this request (e.g., via compromised logs or network sniffing) can resend it repeatedly, causing multiple transfers from the same from account. Axum's extractors provide no automatic defense; the developer must explicitly implement replay mitigation, often using tower middleware to inspect headers or request bodies before they reach the handler.

Axum-Specific Detection

Detecting replay vulnerabilities in Axum APIs requires testing whether the server processes identical, authenticated requests more than once. Manual testing involves capturing a legitimate request (e.g., with Burp Suite) and resending it unchanged; if the operation repeats (e.g., two database writes for a single action), the endpoint is vulnerable.

Automated scanning with middleBrick simulates this attack pattern during its 12 parallel security checks. When you submit an Axum API endpoint to middleBrick, it:

  • Sends sequential, identical requests with valid authentication (if the endpoint requires it, middleBrick uses provided credentials or tests unauthenticated paths).
  • Monitors for side effects: duplicate resource creation, repeated state changes, or identical responses with different transaction IDs.
  • Flags the issue under the Authentication or BOLA/IDOR category, depending on whether the replay bypasses authorization checks.

For example, scanning an Axum payment endpoint might yield a finding like:

CheckSeverityEvidence
Authentication: Replay Protection MissingHighIdentical POST /transfer requests processed 3/3 times

middleBrick's black-box approach works without source code access, making it suitable for any Axum deployment—whether behind Cloudflare, on AWS, or self-hosted. The scan completes in 5–15 seconds, and the report includes prioritized remediation guidance specific to Axum's middleware model. You can run this scan via the Web Dashboard, CLI tool (middlebrick scan https://api.example.com/transfer), or integrate it into CI/CD with the GitHub Action to catch replay flaws before deployment.

Axum-Specific Remediation

Fixing replay attacks in Axum requires implementing middleware that validates request uniqueness before passing control to handlers. The recommended approach uses a tower::Layer to generate or validate a nonce (number used once) stored in a fast, time-bound cache (e.g., Redis, in-memory HashMap for demo). Axum's middleware system via axum::middleware integrates seamlessly.

Step 1: Create a nonce store. For production, use a distributed cache like Redis with a short TTL (e.g., 5 minutes). Here's a simplified in-memory example:

use std::collections::HashSet;
use std::sync::Arc;
use tokio::sync::RwLock;

#[derive(Clone)]
struct NonceStore {
set: Arc<RwLock<HashSet<String>>>,
ttl_seconds: u64,
}

impl NonceStore {
fn new(ttl_seconds: u64) -> Self {
Self {
set: Arc::new(RwLock::new(HashSet::new())),
ttl_seconds,
}
}
async fn validate_and_insert(&self, nonce: &str) -> bool {
let mut set = self.set.write().await;
if set.contains(nonce) {
false // replay detected
} else {
set.insert(nonce.to_string());
// In production, schedule cleanup after TTL
true
}
}
}

Step 2: Build middleware that checks a X-Nonce header. The middleware should reject replays with 409 Conflict or 400 Bad Request:

use axum::{
body::Body,
http::{Request, Response, StatusCode},
middleware::Next,
extract::RequestParts,
};

async fn replay_protection_middleware(
req: Request,
next: Next,
) -> Result, StatusCode> {
let nonce = req
.headers()
.get(

Axum-Specific Remediation (continued)

Step 2 (continued):

X-Nonce

Frequently Asked Questions

Can middleBrick detect replay attacks in Axum APIs?
Yes. middleBrick's Authentication check sends sequential, identical requests to state-changing endpoints and monitors for duplicate processing. If the Axum API replays the same operation (e.g., creating two resources from one request), middleBrick flags it as a high-severity replay vulnerability with specific remediation steps for Axum middleware.
What Axum-specific code fixes does middleBrick recommend for replay attacks?
middleBrick's reports guide you to implement tower middleware in Axum that validates a unique, single-use nonce (e.g., from an X-Nonce header) against a cache like Redis. The fix includes sample Rust code using axum::middleware::from_fn to reject replays with 409 Conflict, aligning with Axum's async, middleware-driven architecture.