HIGH http request smugglingaxummutual tls

Http Request Smuggling in Axum with Mutual Tls

Http Request Smuggling in Axum with Mutual Tls — how this specific combination creates or exposes the vulnerability

HTTP Request Smuggling exploits discrepancies in how a server and a downstream parser handle message framing—typically around Content-Length versus Transfer-Encoding, or the handling of ambiguous chunked encodings. Axum, a Rust web framework, does not introduce its own HTTP parser; it relies on the underlying hyper stack. When Mutual TLS (mTLS) is enforced, the TLS termination and client certificate validation occur before requests reach Axum’s routing logic. While mTLS ensures strong client authentication, it does not normalize or reconcile parsing differences between the edge proxy and the application layer. If an Axum service sits behind a reverse proxy or load balancer that terminates TLS and forwards requests over HTTP to Axum, the proxy may accept request structures that Axum interprets differently. For example, a request with both Content-Length and Transfer-Encoding: chunked might be accepted by the proxy but cause Axum to parse the body in an unexpected way, potentially allowing an attacker to smuggle a request into a subsequent pipeline. The presence of mTLS can create a false sense of security: the channel is encrypted and authenticated, but the application remains vulnerable to request splitting or injection because the parsing boundary is not consistently enforced. Attackers can craft requests where the smuggled request is not subject to the same client certificate checks if the proxy forwards only the initial request and the smuggled segment reaches Axum as a separate, unauthenticated transaction. This is especially relevant when the proxy applies relaxed parsing rules compared to Axum’s strict adherence to RFC 9112. Because Axum does not inherently validate that a request is fully consumed or that no additional messages are appended, an adversary may exploit this to inject a second request that bypasses intended authorization checks, leading to BOLA/IDOR or unauthorized operations. The vulnerability is not in mTLS itself, but in the interaction between transport-layer security and the framework’s handling of ambiguous or malformed messages across different parsing stages.

Mutual Tls-Specific Remediation in Axum — concrete code fixes

Remediation focuses on ensuring consistent parsing behavior and strict request validation regardless of mTLS presence. Do not rely on TLS termination to sanitize requests; enforce canonical HTTP parsing at the application level. When configuring Axum with mTLS, validate client certificates and then ensure the request pipeline rejects messages with ambiguous framing. Below is a concrete Axum setup using hyper::server::conn::http1 with a service that enforces strict HTTP compliance and integrates mTLS via Rustls.

use axum::Router;
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper_util::rt::TokioIo;
use std::net::SocketAddr;
use tokio::net::TcpListener;
use tls_rustls::ServerConfig;

async fn run_axum_with_mtls() {
    // Build Rustls server config with client authentication required
    let mut server_config = ServerConfig::builder()
        .with_safe_defaults()
        .with_client_auth(); // Enforce client cert verification

    let listener = TcpListener::bind("0.0.0.0:8443").await.unwrap();
    let service = service_fn(|req: hyper::Request<hyper::Body>| async move {
        // Axum routing would be integrated here; this example shows raw handling
        // Reject requests with both Content-Length and Transfer-Encoding
        if req.headers().get("content-length").is_some()
            && req.headers().get("transfer-encoding").is_some()
        {
            return Ok::<_, hyper::Error>(hyper::Response::builder()
                .status(400)
                .body(hyper::Body::from("Invalid framing: conflicting headers")[..])
                .unwrap());
        }
        // Proceed with Axum router in real usage
        Ok::<_, hyper::Error>(hyper::Response::new(hyper::Body::from("OK")))
    });

    let conn = http1::Builder::new()
        .enforce_http(false) // Let application handle HTTP compliance
        .serve_connection(TokioIo::new(listener.accept().await.unwrap().1), service);
    conn.await.unwrap();
}

In addition to code-level fixes, apply these practices:

  • Use a reverse proxy that normalizes requests before forwarding to Axum, ensuring consistent Content-Length and Transfer-Encoding handling.
  • Reject requests containing both Content-Length and Transfer-Encoding headers at the edge, regardless of mTLS status.
  • Configure client certificate validation to be strict and verify that the proxy does not alter the request stream in a way that reintroduces ambiguity.
  • Leverage Axum’s extractor validation to ensure the request body is consumed entirely and no additional data is appended, reducing the risk of smuggling via pipelined requests.

These steps mitigate smuggling risks while preserving the security benefits of mTLS, acknowledging that transport security does not equate to HTTP message integrity.

Frequently Asked Questions

Does mTLS prevent HTTP request smuggling in Axum?
No. Mutual TLS authenticates the client and encrypts the channel, but it does not normalize HTTP parsing between the proxy and Axum. Smuggling can still occur if request framing differs across layers.
How can I detect smuggling risks in an mTLS-enabled Axum deployment?
Use middleBrick to scan your endpoint. It tests unauthenticated attack surfaces and can identify inconsistent handling of Content-Length and Transfer-Encoding, even when mTLS is in place. Combine mTLS with strict header validation at the application level for comprehensive protection.