Security Misconfiguration in Axum with Mutual Tls
Security Misconfiguration in Axum with Mutual Tls — how this specific combination creates or exposes the vulnerability
Security misconfiguration in an Axum service that uses Mutual TLS (mTLS) often arises when the server enforces client certificate verification but does not fully validate the client identity or the certificate properties. This can leave the application surface open even though transport encryption is in place.
For example, an Axum server may be configured to request client certificates via rustls::ServerConfig but skip essential checks such as verifying that the client certificate is within its validity period, confirming the certificate chain against a trusted root, or validating the Extended Key Usage or Key Usage extensions. If the server accepts any presented certificate without these validations, an attacker could supply a self‑signed or expired certificate and be treated as an authenticated client.
Another common misconfiguration is binding mTLS only to a subset of routes while leaving other endpoints unauthenticated or weakly authenticated. This inconsistency can allow an attacker to bypass the protected paths by interacting with the less‑protected routes. Additionally, failing to set appropriate TLS versions and cipher suites can expose the service to known protocol vulnerabilities that undermine the protections mTLS is meant to provide.
Runtime findings from a scan can reveal mismatches between the expected client identity and what the application actually trusts. For instance, the scanner might detect that the server accepts client certificates that do not match the intended access control list or that lack the required constraints. Such findings highlight that encryption in transit does not equate to authenticated authorization, a common oversight when mTLS is added without thorough configuration review.
Because middleBrick scans the unauthenticated attack surface, it can flag these misconfigurations without requiring credentials, helping teams understand how incomplete mTLS setups weaken the intended security guarantees in Axum services.
Mutual Tls-Specific Remediation in Axum — concrete code fixes
To properly secure an Axum service with Mutual TLS, enforce strict certificate validation and apply least‑privilege access controls. Below are concrete steps and code examples.
1. Configure rustls to require and validate client certificates
Load a trusted root CA and set client_auth to require client certificates. Validate the certificate chain, check the validity period, and inspect extensions.
use axum::Server;
use rustls::{Certificate, PrivateKey, ServerConfig};
use rustls_pemfile::{certs, pkcs8_private_keys};
use std::fs::File;
use std::io::BufReader;
use std::net::SocketAddr;
use std::sync::Arc;
async fn make_rustls_config() -> Arc<ServerConfig> {
let mut cert_file = BufReader::new(File::open("ca.crt").expect("cannot open CA cert"));
let mut key_file = BufReader::new(File::open("server.key").expect("cannot open server key"));
let cert_chain: Vec<Certificate> = certs(&mut cert_file)
.collect::
2. Enforce strong TLS versions and cipher suites
Limit protocols to TLSv1.2 and TLSv1.3 and prefer strong cipher suites to reduce attack surface.
use rustls::{ProtocolVersion, CipherSuite};
let mut config = ServerConfig::builder()
.with_safe_defaults()
.with_client_auth(client_auth)
.with_single_cert(cert_chain, keys.remove(0))
.expect("invalid certificate or key");
// Explicitly set allowed protocols and cipher suites
config.versions = vec![ProtocolVersion::TLSv1_2, ProtocolVersion::TLSv1_3];
config.ciphersuites = vec![
CipherSuite::TLS13_CHACHA20_POLY1305_SHA256,
CipherSuite::TLS13_AES_256_GCM_SHA384,
];
let tls_config = Arc::new(config);
3. Apply route-level authentication and authorization
Even with mTLS, validate the client identity per request and enforce role‑based access control at the handler level.
use axum::{routing::get, Router, extract::State};
use std::collections::HashSet;
struct AppState {
allowed_subjects: HashSet<String>,
}
async fn handler(
State(state): State<AppState>,
client_cert: axum_extra::extract::ClientCert,
) -> &'static str {
if let Some(cert) = client_cert.cert {
let subject = cert.subject().to_string();
if state.allowed_subjects.contains(subject.as_str()) {
return "authorized";
}
}
"unauthorized"
}
#[tokio::main]
async fn main() {
let mut allowed = HashSet::new();
allowed.insert("/CN=service-a".to_string());
let app = Router::new()
.route("/api/data", get(handler))
.with_state(AppState { allowed_subjects: allowed });
// attach tls_config as shown earlier
}
4. Rotate and monitor certificates
Use short-lived certificates and automate rotation. Monitor revocation and validate OCSP/CRL where applicable. middleBrick can be integrated into your CI/CD pipeline (GitHub Action) to continuously scan your endpoints and alert you if mTLS-related misconfigurations appear after changes.