Api Rate Abuse in Axum with Saml
Api Rate Abuse in Axum with Saml — how this specific combination creates or exposes the vulnerability
Rate abuse in an Axum application using SAML for authentication can occur when rate limiting is applied after authentication rather than on the unauthenticated entry point or on SAML metadata/assertion validation endpoints. Because SAML flows often involve redirects and POST bindings that carry assertions from an identity provider (IdP) to the service provider (Axum app), each step can be targeted to exhaust rate limits or bypass them by manipulating SAML parameters or endpoints.
In a typical setup, the Axum service exposes endpoints such as the SAML metadata endpoint (/saml/metadata) and the SAML assertion consumer service (/saml/acs). If these endpoints do not have independent, unauthenticated rate limits, an attacker can send many crafted SAML requests or metadata queries to consume capacity, cause denial of service, or brute-force identifiers like NameID or inResponseTo values. Even when a broader application-level rate limit exists, SAML-specific paths may be excluded from enforcement, creating a bypass vector.
Another scenario involves the SP-initiated flow where the Axum app generates an authentication request and redirects the user to the IdP. If the application does not enforce rate limits on the creation of authentication requests per session or per originating IP, an attacker can trigger excessive requests that lead to session exhaustion or amplify other issues such as XML External Entity (XXE) or Server-Side Request Forgery (SSRF) when the IdP endpoint is reachable. Because SAML messages are often large and include signed or encrypted assertions, processing each request imposes more server work than a simple HTTP request, making the rate abuse impact more severe.
Additionally, if Axum relies on a SAML library that caches or parses metadata without strict validation, repeated requests for metadata with different entity IDs or certificate parameters can force repeated parsing and key loading, increasing resource consumption. In an unauthenticated scan, such endpoints can be enumerated and abused to degrade performance or to indirectly facilitate further attacks like injection or token replay.
Because middleBrick tests unauthenticated attack surfaces and includes rate limiting checks among its 12 parallel security checks, it can identify whether SAML-related paths are missing adequate protection. The scanner looks for missing or inconsistent rate limiting on authentication flows and surfaces findings with severity and remediation guidance, helping teams ensure that SAML endpoints are treated as high-risk paths subject to the same controls as any other public API surface.
Saml-Specific Remediation in Axum — concrete code fixes
Remediation focuses on applying rate limits before and around SAML processing, normalizing inputs, and ensuring metadata and assertion handling are resilient to abuse. Below are concrete Axum examples using tower-http middleware for rate limiting and proper SAML endpoint handling.
1. Apply rate limits to SAML endpoints
Ensure that /saml/metadata and /saml/acs are protected by rate limits independent of authenticated user limits. Use a per-IP or per-session key to prevent an attacker from exhausting the service via SAML paths.
use axum::routing::get;
use axum::Router;
use tower_http::rate_limit::{RateLimitLayer, RateLimitLayerError};
use std::net::SocketAddr;
fn build_app() -> Router {
let rate_limit_layer = RateLimitLayer::new(100, std::time::Duration::from_secs(60));
Router::new()
.route("/saml/metadata", get(saml_metadata).layer(rate_limit_layer.clone()))
.route("/saml/acs", post(saml_acs).layer(rate_limit_layer))
// other routes
}
async fn saml_metadata() -> String {
// Return metadata XML
String::new()
}
async fn saml_acs() -> String {
// Process SAML response
String::new()
}
#[tokio::main]
async fn main() {
let app = build_app();
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").unwrap();
axum::serve(listener, app).await.unwrap();
}
2. Normalize and validate SAML inputs to prevent parameter abuse
Validate entity IDs, AssertionConsumerService URLs, and NameID formats before using them. Reject malformed or suspicious values to reduce probing surface.
use axum::extract::Form;
use serde::Deserialize;
#[derive(Deserialize)]
struct SamlRequest {
SAMLRequest: String,
RelayState: Option,
}
async fn saml_acs(Form(payload): Form) -> Result {
if !is_valid_saml_request(&payload.SAMLRequest) {
return Err((axum::http::StatusCode::BAD_REQUEST, "Invalid SAML request".into()));
}
// proceed with parsing
Ok("OK".into())
}
fn is_valid_saml_request(req: &str) -> bool {
// Basic sanity checks before decoding
!req.is_empty() && req.len() < 10_000
}
3. Enforce rate limits on SP-initiated request creation
If your app generates AuthnRequest objects on the server side (e.g., for SP-initiated flows), rate limit per session or per client IP to prevent request amplification.
use tower_http::rate_limit::RateLimitLayer;
use std::time::Duration;
let sp_init_rate_limit = RateLimitLayer::new(5, Duration::from_secs(10));
// Apply to route that creates AuthnRequest:
app.route("/login/sp", get(create_authn_request).layer(sp_init_rate_limit));
4. Harden metadata fetching and caching
If you fetch remote IdP metadata, enforce strict timeouts and limit repetitive requests to the same entity ID within a window. Use a simple in-memory or distributed cache with request counting to avoid repeated expensive operations.
// Pseudo-code outline: track request counts per entity_id
// Reject or delay if count exceeds threshold within a sliding window.
5. Align SAML flows with broader rate limiting strategy
Make sure SAML endpoints are included in your global rate limit configuration and that limits are applied before routing to handlers. Avoid excluding authentication paths from enforcement.
By combining these Axum-specific fixes with middleBrick’s unauthenticated scans, teams can verify that SAML routes are not only functionally correct but also resilient to rate abuse and enumeration probes.