HIGH phishing api keysaxummutual tls

Phishing Api Keys in Axum with Mutual Tls

Phishing API Keys in Axum with Mutual TLS — how this specific combination creates or exposes the vulnerability

Mutual Transport Layer Security (mTLS) in Axum adds client certificate verification on top of server-side TLS, which is intended to strengthen identity assurance. However, even when mTLS is correctly configured, developers can inadvertently expose API keys through application-layer handling, error messages, or logging. Phishing of API keys in this context often occurs via social engineering or compromised client-side tooling rather than a protocol weakness in mTLS itself. For example, an attacker might trick a client into using a malicious proxy or a rogue client certificate that forwards credentials to an attacker-controlled endpoint. In Axum, if route handlers log raw headers or query parameters that include keys, and those logs are exposed, keys can be harvested. Similarly, if the client certificate verification is bypassed or misconfigured (for example, by not validating the certificate chain or by trusting any certificate when under debug), an attacker can present any certificate and still reach the endpoint, then phish credentials through a fake UI or callback. Compromised client tooling that stores keys in environment variables or files that are later accessed by malicious actors also creates a phishing surface. In an mTLS-enabled Axum service, a misconfigured trust store or a missing verification callback can lead to unauthenticated access paths where an attacker can probe for information leakage. The 12 parallel security checks in middleBrick include Authentication and BOLA/IDOR, which help detect whether mTLS-enforced identity is being respected and whether keys are exposed through insecure endpoints. Because middleBrick scans unauthenticated attack surfaces, it can flag endpoints that return sensitive data such as keys in responses or headers, or that do not enforce client certificate validation as expected.

Mutual TLS-Specific Remediation in Axum — concrete code fixes

Remediation focuses on strict certificate validation, avoiding key leakage in logs and responses, and ensuring the server only accepts trusted client certificates. Below are concrete Axum examples that demonstrate a secure mTLS setup.

1. Configure TLS acceptor with client certificate verification

Use rustls to require and verify client certificates against a trusted CA. This ensures only presented certificates signed by the expected CA are accepted.

use axum::Server;
use std::net::SocketAddr;
use tokio_rustls::rustls::{ServerConfig, Certificate, PrivateKey, NoClientAuth};
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer};
use tokio_rustls::TlsAcceptor;
use std::sync::Arc;

async fn make_secure_acceptor() -> TlsAcceptor {
    // Load server cert and key
    let cert_chain = vec![CertificateDer::from(std::fs::read("certs/server.crt").unwrap())];
    let priv_key = PrivateKeyDer::Pkcs8(std::fs::read("certs/server.key").unwrap().into());

    // Load trusted CA for client cert verification
    let client_ca = CertificateDer::from(std::fs::read("certs/ca.crt").unwrap());

    let mut server_config = ServerConfig::builder()
        .with_safe_defaults()
        .with_no_client_auth() // start without client auth
        .with_single_cert(cert_chain, priv_key)
        .expect("invalid server cert or key");

    // Require and verify client certificates
    let client_auth = rustls::server::ClientAuthMandatory::Required(vec![client_ca]);
    server_config.client_auth = Some(client_auth);

    let tls_acceptor = TlsAcceptor::from(Arc::new(server_config));
    tls_acceptor
}

#[tokio::main]
async fn main() {
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    let tls_acceptor = make_secure_acceptor().await;

    let app = axum::Router::new()
        .route("/health", axum::routing::get(|| async { "ok" }));

    Server::bind(&addr)
        .tls_config(tls_acceptor)
        .expect("valid TLS config")
        .serve(app.into_make_service())
        .await
        .unwrap();
}

2. Avoid logging or echoing sensitive headers and query parameters

Ensure handlers do not include API keys or tokens in logs, JSON responses, or error details. Use extractor patterns that omit sensitive data from debug output.

use axum::{routing::get, Router, extract::Query};
use serde::Deserialize;

#[derive(Deserialize)]
struct Params {
    api_key: Option,
    token: Option,
}

async fn handler(Query(params): Query) -> String {
    // Never log raw keys; if needed for auditing, hash or redact them
    let key_present = params.api_key.is_some();
    // Process without exposing the key in strings or logs
    if key_present {
        "authorized".to_string()
    } else {
        "unauthorized".to_string()
    }
}

fn app() -> Router {
    Router::new().route("/check", get(handler))
}

3. Enforce certificate verification programmatically when needed

For advanced control, customize verification via rustls::ServerConfigBuilder to reject expired or improperly constrained certificates.

use tokio_rustls::rustls::{ServerConfig, RootCertStore, Certificate, PrivateKey};
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer};

fn make_strict_acceptor() -> TlsAcceptor {
    let mut roots = RootCertStore::empty();
    roots.add(&CertificateDer::from(std::fs::read("certs/ca.crt").unwrap()))
        .expect("failed to add CA");

    let cert_chain = vec![CertificateDer::from(std::fs::read("certs/server.crt").unwrap())];
    let priv_key = PrivateKeyDer::Pkcs8(std::fs::read("certs/server.key").unwrap().into());

    let mut server_config = ServerConfig::builder()
        .with_safe_defaults()
        .with_client_cert_verifier(Arc::new(roots)) // strict verification
        .with_single_cert(cert_chain, priv_key)
        .expect("invalid certs");

    // Ensure no fallback to no-client-auth
    server_config.client_auth = Some(rustls::server::ClientAuthMandatory::Required(vec![
        roots.clone().into(),
    ]));

    TlsAcceptor::from(Arc::new(server_config))
}

4. Secure client tooling and environment

Store client certificates and API keys in platform-secured stores (e.g., secret managers), and avoid embedding keys in code or configs that can be phished. Rotate keys regularly and monitor for unexpected certificate presentations using middleBrick’s Authentication and BOLA/IDOR checks.

Frequently Asked Questions

Can mTLS alone prevent API key phishing in Axum?
mTLS strengthens transport identity but does not prevent phishing if keys are leaked through logs, error messages, or compromised client tooling. Secure handling, redaction, and strict certificate validation are still required.
How does middleBrick help detect API key exposure in mTLS setups?
middleBrick’s Authentication and BOLA/IDOR checks can identify endpoints that return sensitive data such as keys, and it flags weak or missing client certificate validation that could allow unauthorized access.