Denial Of Service in Axum with Dynamodb
Denial Of Service in Axum with Dynamodb — how this specific combination creates or exposes the vulnerability
Axum is a Rust web framework that encourages fast, non-blocking request handling. When an Axum service calls DynamoDB as a backend dependency, DoS risks arise from unbounded concurrency, long-running synchronous wait paths, and retry storms. A single DynamoDB throttling event can cause worker threads or async tasks to pile up, consuming memory and connection resources until the service becomes unresponsive.
DynamoDB can throttle requests when provisioned capacity is exceeded or when bursts trigger account-level limits. In Axum, if each incoming request performs a strongly consistent read or a write without concurrency control, the resulting retry backoff and queueing can saturate the runtime. For example, a missing index query that results in a full table scan on the server side can amplify read units consumption and increase latency, which in turn keeps request futures pinned longer than expected.
The combination is dangerous when Axum endpoints perform inefficient queries (e.g., repeated GetItem calls in a loop) or when SDK clients are not configured with appropriate timeouts and concurrency limits. Without explicit bounds, a burst of traffic that would normally be handled gracefully can cascade into a wider DoS, where legitimate requests are delayed or dropped because runtime resources are exhausted by blocked or retrying calls to DynamoDB.
An attacker does not need authentication to trigger this class of issue. Public endpoints that issue heavy DynamoDB operations—such as search or batch lookups—are especially susceptible. Instrumentation that does not surface per-call latency and error metrics can hide the problem until the service becomes noticeably slow or fails to serve requests.
Dynamodb-Specific Remediation in Axum — concrete code fixes
Apply explicit concurrency limits, timeouts, and backpressure when using DynamoDB from Axum. Use non-blocking SDK clients, bound the number of in-flight requests, and fail fast when downstream pressure is high.
use aws_sdk_dynamodb::Client;
use std::sync::Arc;
use tokio::sync::Semaphore;
use std::time::Duration;
use axum::{routing::get, Router};
struct AppState {
client: Client,
table_name: String,
concurrency_limit: Arc,
}
async fn get_item_handler(
state: Arc<AppState>,
axum::extract::Path(key): axum::extract::Path<String>,
) -> Result<impl axum::response::IntoResponse, (axum::http::StatusCode, String)> {
// Apply backpressure instead of unbounded concurrency
let _permit = state.concurrency_limit.acquire().await.map_err(|_| {
(axum::http::StatusCode::SERVICE_UNAVAILABLE, "service overloaded".to_string())
})?;
let resp = tokio::time::timeout(
Duration::from_millis(800),
state.client.get_item()
.table_name(&state.table_name)
.key("id", aws_sdk_dynamodb::types::AttributeValue::S(key))
.consistent_read(true)
.send(),
).await.map_err(|_| {
(axum::http::StatusCode::GATEWAY_TIMEOUT, "dynamodb timeout".to_string())
})??;
match resp.item() {
Some(item) => Ok(axum::Json(serde_json::json!({ "item": item }))),
None => Err((axum::http::StatusCode::NOT_FOUND, "not found".to_string())),
}
}
#[tokio::main]
async fn main() {
let config = aws_config::load_from_env().await;
let client = Client::new(&config);
let state = Arc::new(AppState {
client,
table_name: "widgets".to_string(),
concurrency_limit: Arc::new(Semaphore::new(50)), // bound parallelism
});
let app = Router::new()
.route("/items/:id", get(get_item_handler))
.with_state(state);
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
In this pattern, the semaphore restricts the number of concurrent requests that can proceed to DynamoDB, preventing thread exhaustion. A per-request timeout ensures that slow or throttled calls do not hold resources indefinitely. Use exponential backoff with jitter in production SDK clients, and prefer Query or BatchGetItem over repeated GetItem calls to reduce request volume.
For higher throughput, enable client-side caching for read-heavy paths and design indexes to avoid full table scans. Monitor consumed read capacity units and set alarms so you can react before queue lengths grow. These practices reduce the likelihood that a burst of traffic or a downstream throttle event turns into a service-wide denial of service in Axum services that rely on DynamoDB.
Related CWEs: resourceConsumption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-400 | Uncontrolled Resource Consumption | HIGH |
| CWE-770 | Allocation of Resources Without Limits | MEDIUM |
| CWE-799 | Improper Control of Interaction Frequency | MEDIUM |
| CWE-835 | Infinite Loop | HIGH |
| CWE-1050 | Excessive Platform Resource Consumption | MEDIUM |