HIGH denial of serviceactixmutual tls

Denial Of Service in Actix with Mutual Tls

Denial Of Service in Actix with Mutual Tls — how this specific combination creates or exposes the vulnerability

Mutual Transport Layer Security (mTLS) in Actix requires both the client and server to present valid certificates during the TLS handshake. While mTLS strengthens identity verification, it introduces additional processing overhead that can amplify Denial of Service (DoS) risks compared to one-way TLS. The combination creates exposure in three dimensions: handshake cost, connection handling, and request parsing.

During the TLS handshake, mTLS involves additional cryptographic operations such as client certificate validation, revocation checks (e.g., CRL or OCSP), and signature verification. In Actix, if these operations are performed on the accepting actor for every connection without tuning, the CPU cost per handshake can become significant under high concurrency. An attacker can open many concurrent TLS connections and force the server to perform expensive mTLS handshakes, exhausting CPU or worker threads. This is a resource exhaustion vector that manifests as a high-severity risk in the Authentication and Rate Limiting checks of a middleBrick scan.

Connection lifecycle management also contributes to DoS potential. Actix applications that accept TLS streams but do not enforce strict timeouts for the TLS handshake or early data can leave sockets in a half-open state. If the server waits indefinitely for client certificates or application-level HTTP data, file descriptors and memory buffers may be held by idle connections. In a scenario where the server also parses request bodies before authorization, an attacker might send partial or malformed requests that consume buffers. The BOLA/IDOR and Input Validation checks in middleBrick highlight cases where unauthenticated endpoints accept large or malformed payloads, increasing the likelihood of resource saturation.

The interplay of mTLS and HTTP semantics in Actix can exacerbate parsing-based DoS. For example, if the server uses permissive content-type handling or large default payload limits, an attacker can send carefully crafted requests that trigger expensive deserialization or body accumulation. This amplifies the impact of vulnerabilities flagged by the Property Authorization and Unsafe Consumption checks. middleBrick detects these patterns by correlating TLS-level metadata with runtime behavior, noting cases where unauthenticated endpoints exhibit unusually high resource consumption during probing.

Mutual Tls-Specific Remediation in Actix — concrete code fixes

Apply mTLS hardening and resource controls in Actix to reduce DoS exposure. These examples assume you are using native Rust TLS with acceptor configuration; adapt as needed for your runtime.

1. Limit handshake concurrency and set timeouts

Restrict the number of concurrent TLS handshakes and enforce deadlines to prevent resource exhaustion. Use Actix server builder settings and Tokio timeouts to bound connection setup cost.

use actix_web::{web, App, HttpServer};
use std::time::Duration;
use tokio_rustls::rustls::ServerConfig;
use tokio_rustls::TlsAcceptor;
use std::sync::Arc;

async fn config_tls() -> Arc<TlsAcceptor> {
    let mut config = ServerConfig::builder()
        .with_safe_defaults()
        .with_no_client_auth() // will be replaced with client auth
        .with_client_cert_verifier(Arc::new(|_end_entity, _intermediates| Ok(()))); // customize as needed
    // Load server cert and key
    config.set_single_cert(vec![], vec![]); // provide certs and key in real code
    let tls_acceptor = TlsAcceptor::from(Arc::new(config));
    Arc::new(tls_acceptor)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let tls_acceptor = config_tls().await;
    HttpServer::new(move || {
        App::new()
            .wrap(actix_web::middleware::Logger::default())
            .service(web::resource("/")
                .route(web::get().to(|| async { "ok" })))
    })
    .bind_rustls(
        "127.0.0.1:8443",
        tls_acceptor.clone(),
    )?
    .accept_timeout(Duration::from_secs(5)) // limit handshake time
    .max_http_version1(100) // bound concurrent connections as appropriate
    .run()
    .await
}

2. Enforce client certificate validation constraints

Validate client certificates efficiently and avoid overly permissive verifications that can be forced to consume excessive cycles. Prefer stapled OCSP where available and set reasonable verification depth.

use rustls::{ClientCertVerified, ServerCertVerified, TLSError};
use std::time::SystemTime;

fn client_cert_verifier() -> Arc<dyn Fn(Vec<rustls::Certificate>, &rustls::WebPkiDNServerSession) -> Result<ClientCertVerified, TLSError>> {
    Arc::new(|certs, _session| {
        // Implement short-circuit checks to reduce CPU per handshake
        if certs.is_empty() {
            return Err(TLSError::NoCertificatesPresented);
        }
        // Example: basic validity window check to avoid heavy CRL/OCSP in hot path
        // In production, use a verifier that leverages stapling and cached results
        Ok(ClientCertVerified::assertion())
    })
}

3. Apply request size and body limits early

Reject or close connections that exceed payload thresholds before consuming significant buffer space. Configure payload limits at the Actix app or service level to protect parsing stages flagged by Property Authorization and Unsafe Consumption checks.

use actix_web::{middleware, web, App, HttpServer};

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .wrap(middleware::Logger::default())
            .configure(|cfg| {
                cfg.service(
                    web::resource("/api/upload")
                        .route(web::post().to(|| async { "upload" }))
                        .app_data(web::JsonConfig::default().limit(4096)) // limit JSON body
                        .app_data(web::PayloadConfig::new(64 * 1024)), // overall payload cap
                );
            })
    })
    .bind_rustls(
        "0.0.0.0:8443",
        tls_acceptor().await,
    )?
    .run()
    .await
}

4. Use connection and rate limits aligned with mTLS cost

Configure per-IP connection and request rate limits to mitigate handshake amplification. Combine with middleware to enforce policies before expensive certificate operations are triggered.

use actix_web::middleware::errhandlers::ErrorHandlers;
use actix_web::dev::ServiceRequest;
use actix_web::error::ErrorTooManyRequests;
use actix_web::Either;

fn rate_limited_app() -> App {
    App::new()
        .wrap(ErrorHandlers::new().handler(actix_web::http::StatusCode::TOO_MANY_REQUESTS, |res| {
            async move { Either::Left(res.error_response()) }
        }))
        .service(web::resource("/").to(|| async { "limited" }))
}

Related CWEs: resourceConsumption

CWE IDNameSeverity
CWE-400Uncontrolled Resource Consumption HIGH
CWE-770Allocation of Resources Without Limits MEDIUM
CWE-799Improper Control of Interaction Frequency MEDIUM
CWE-835Infinite Loop HIGH
CWE-1050Excessive Platform Resource Consumption MEDIUM

Frequently Asked Questions

How does mTLS increase DoS risk in Actix compared to one-way TLS?
mTLS adds CPU-intensive certificate validation and revocation checks per handshake. If not bounded, concurrent mTLS handshakes can exhaust worker threads and CPU, enabling resource exhaustion DoS. middleBrick flags elevated Authentication and Rate Limiting risks when it detects unauthenticated endpoints that also incur high handshake cost.
Can middleware or server settings alone fully prevent mTLS-related DoS?
No. You should combine handshake timeouts, connection and rate limits, early payload size caps, and efficient client certificate validation. middleBrick helps identify insecure configurations and unauthenticated endpoints with high resource consumption to guide remediation.