Auth Bypass in Axum with Saml
Auth Bypass in Axum with Saml — how this specific combination creates or exposes the vulnerability
An Auth Bypass in an Axum application using SAML occurs when the integration does not enforce strict validation of the SAML response or the identity of the relying party. Axum is a Rust web framework, and when SAML is used, the application typically relies on a SAML library to process assertions. If the implementation does not validate the audience restriction (Audience), the Issuer (Issuer), or the signature of the SAML response, an attacker can supply a token issued for another service or a forged assertion and gain unauthorized access.
In a black-box scan, middleBrick tests the unauthenticated attack surface and checks whether endpoints that should require SAML authentication are accessible without a valid assertion. One common misconfiguration is failing to set the correct recipient URL in the SAML request or relying party configuration, which can allow an attacker to submit a response intended for a different service. Another risk is missing or improper validation of the NameID format and the Subject confirmation method. If the application trusts the Subject without verifying the SubjectConfirmationData Recipient and InResponseTo fields, an attacker can reuse a captured assertion.
middleBrick’s 12 security checks run in parallel and include Authentication and BOLA/IDOR evaluations. For SAML-based Axum services, the scanner verifies whether the endpoint validates the SAML response signature, audience, issuer, and session index. Findings may map to the OWASP API Security Top 10 category Broken Object Level Authorization (BOLA) when access is granted based solely on the presence of a SAML assertion without ensuring the subject is authorized for the requested resource. The scan also checks for missing rate limiting on the SAML Assertion Consumer Service (ACS) endpoint, which could enable credential stuffing or token replay attacks.
Real-world examples include CVE scenarios where an attacker crafts a SAML response with an elevated NameID or manipulates the AttributeStatement to claim administrative roles. If the Axum application does not verify the attribute values against an authorization source, the attacker can be granted elevated privileges. Data Exposure checks may reveal that sensitive identity attributes are passed in the SAML response without encryption, violating best practices even when transport layer encryption is in place.
To detect these issues, middleBrick analyzes the OpenAPI specification if available and cross-references runtime behavior with the SAML flow. The scanner does not assume the presence of authentication headers; it probes the ACS endpoint and related authentication flows to confirm whether SAML assertions are validated correctly. This approach helps identify gaps in configuration that could lead to authentication bypass in Axum services that rely on SAML.
Saml-Specific Remediation in Axum — concrete code fixes
Remediation for Auth Bypass when using SAML in Axum centers on strict validation of the SAML response and tightening the configuration of the relying party. Use a maintained Rust SAML library that supports schema validation, signature verification, and audience restriction. Ensure that the Audience condition in the SAML assertion matches the service provider entity ID configured in Axum. Always verify the Issuer against a whitelist of trusted identity providers and check the Subject ConfirmationMethod to ensure it includes urn:oasis:names:tc:SAML:2.0:cm:bearer only when appropriate and paired with valid SubjectConfirmationData.
Configure the ACS endpoint to reject assertions with missing or mismatched InResponseTo and Destination fields. Implement session management that ties the SAML assertion to a secure, server-side session and invalidate sessions on logout. Enforce HTTPS for all SAML endpoints and require signed assertions. Below is a simplified example of configuring a SAML service provider in Rust using the saml2 crate, focusing on audience and issuer validation.
use saml2::core::saml2::assertion::Assertion;
use saml2::core::saml2::name_id::NameID;
use saml2::core::saml2::conditions::Conditions;
use saml2::core::saml2::subject::Subject;
use saml2::core::saml2::subject_confirmation::SubjectConfirmation;
use saml2::core::saml2::subject_confirmation_data::SubjectConfirmationData;
use saml2::core::saml2::name_id_format::NameIDFormat;
use saml2::core::saml2::authn_statement::AuthnStatement;
use saml2::core::saml2::attribute_statement::AttributeStatement;
use saml2::core::saml2::protocol::Response;
use saml2::validator::validate_response;
async fn handle_saml_acs(response_xml: &str, expected_audience: &str, expected_issuer: &str) -> Result<(), String> {
let response: Response = serde_xml_rs::from_str(response_xml)
.map_err(|e| format!("Failed to parse SAML response: {}", e))?;
// Validate issuer
if response.issuer.as_ref().map_or(true, |issuer| issuer.value != expected_issuer) {
return Err("Invalid issuer".into());
}
// Validate conditions including audience
let conditions = response.assertion.as_ref()
.and_then(|a| a.conditions.clone())
.ok_or("Missing conditions")?;
if !conditions.audience.iter().any(|a| a.text == expected_audience) {
return Err("Audience mismatch".into());
}
// Ensure subject confirmation
let subject = response.assertion.as_ref()
.and_then(|a| a.subject.clone())
.ok_or("Missing subject")?;
if let SubjectConfirmation::SecurityToken(subject_confirmation) = subject.confirmation {
if subject_confirmation.method != "urn:oasis:names:tc:SAML:2.0:cm:bearer" {
return Err("Unsupported subject confirmation method".into());
}
if let Some(data) = subject_confirmation.subject_confirmation_data {
if data.recipient != expected_audience {
return Err("SubjectConfirmationData recipient mismatch".into());
}
}
} else {
return Err("Invalid subject confirmation type".into());
}
// Verify signature (pseudocode, actual usage depends on library support)
// validate_response(&response).map_err(|e| format!("Validation error: {}", e))?;
// Extract NameID for session creation
let name_id = response.assertion.as_ref()
.and_then(|a| a.name_id.clone())
.ok_or("Missing NameID")?;
if name_id.format != Some(NameIDFormat::Transient) {
return Err("Unsupported NameID format".into());
}
// At this point, the SAML response is considered valid for this service provider
Ok(())
}
Additionally, ensure that the SAML metadata endpoint is protected and that certificate rotation is supported. middleBrick’s Pro plan includes continuous monitoring and can be integrated into your CI/CD pipeline to verify that these validations remain in place after changes. The GitHub Action can fail builds if the scan detects missing audience or issuer checks, helping you prevent regressions before deployment.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |
Frequently Asked Questions
How does middleBrick detect an Auth Bypass involving SAML in an Axum service?
Can the middleBrick CLI be used to test SAML-protected Axum endpoints?
middlebrick scan <url> to submit SAML requests and analyze the authentication flow. The CLI outputs structured findings that highlight missing validations and configuration issues.