Man In The Middle in Actix
How Man In The Middle Manifests in Actix
A Man-In-The-Middle (MITM) attack against an Actix-based API occurs when an adversary intercepts or alters traffic between a client and the server. This is rarely a flaw in Actix's core logic but stems from TLS/SSL configuration weaknesses or application-level trust assumptions. In Rust's Actix-web framework, common manifestation points include:
- Insecure TLS Configuration: Using
rustlsornative-tlswith permissive settings. For example, creating anSslAcceptorwithout explicitly setting a minimum TLS version or allowing legacy cipher suites. A historical example is CVE-2020-17530, where certainrustlsversions allowed connections with TLS 1.0/1.1, making traffic vulnerable to downgrade attacks. - Missing Certificate Validation: When Actix acts as a client (e.g., calling downstream APIs) using
reqwestorsurf, disabling certificate verification (danger_accept_invalid_certs(true)or customrustls::ClientConfigwithdangerous().set_certificate_verifier(...)) creates a MITM vector. - Mixed Content or HTTP Fallback: An Actix server that does not enforce HTTPS via redirects or HSTS headers allows initial connections over plain HTTP, where MITM can occur before any encryption is established.
- Unvalidated Redirects: If an Actix endpoint accepts a URL parameter and issues a redirect (e.g.,
HttpResponse::Found().append_header(("location", url))) without validating the target scheme, an attacker could redirect a user from HTTPS to HTTP.
The attack exploits trust boundaries. If an API relies solely on transport security without additional integrity checks (like signatures), a MITM with a forged certificate (e.g., via compromised CA or user-installed root) can read or modify JSON payloads, tokens, or PII.
Actix-Specific Detection
Detecting MITM vulnerabilities in an Actix API requires examining both the server's TLS handshake and its HTTP behavior.
Manual Inspection
- TLS Configuration Review: Inspect Actix server initialization code. Look for
HttpServer::bind().tls(ssl_acceptor)and verify theSslAcceptorsetup. Red flags include:.set_min_proto_version(Some(Protocol::TLSv1)), or usingrustls::crypto::CryptoProvider::get_default().unwrap().cipher_suiteswithout filtering weak suites (e.g.,TLS_RSA_WITH_AES_128_CBC_SHA). - HTTP-to-HTTPS Enforcement: Check for middleware that redirects HTTP to HTTPS (e.g.,
actix-web::middleware::Redirect) and HSTS header setting (actix-web::middleware::DefaultHeaderswithStrict-Transport-Security). - Outbound Client Configuration: Search for
reqwest::Client::builder().danger_accept_invalid_certs(true)or similar in any service that makes external calls on behalf of the API.
Automated Scanning with middleBrick
middleBrick's Encryption check (one of its 12 parallel security tests) automatically probes an API's TLS configuration. When you submit an Actix endpoint URL to middleBrick, it:
- Performs a TLS handshake analysis, checking for protocol versions, cipher suite strength, certificate validity, and HSTS presence.
- Attempts HTTP connections to verify if the server responds over unencrypted channels.
- Reports findings with a severity score and remediation guidance specific to the detected weakness, such as "Weak cipher suite detected (TLS_RSA_WITH_AES_128_CBC_SHA)" or "No HSTS header."
For example, scanning an Actix API with middlebrick scan https://api.example.com might return a medium-severity finding if TLS 1.0 is enabled, mapping to OWASP API Top 10:API7:2023 – Security Misconfiguration.
You can integrate this into your CI/CD pipeline using the middleBrick GitHub Action. By adding a step that runs middlebrick/scan-action@v1 with your staging API URL, you can fail the build if the Encryption check score drops below a threshold, preventing deployment of Actix services with weak TLS.
Actix-Specific Remediation
Remediation involves hardening the Actix server's TLS stack and enforcing secure transport end-to-end.
1. Configure Strong TLS on the Server
When setting up rustls with Actix, explicitly define a secure configuration:
use actix_web::{web, App, HttpServer, HttpResponse, Responder};
use rustls::{ServerConfig, PrivateKey, Certificate};
use std::fs::File;
use std::io::BufReader;
async fn index() -> impl Responder {
HttpResponse::Ok().body("Hello HTTPS!")
}
async fn main() -> std::io::Result<()> {
// Load certificates
let cert_file = &mut BufReader::new(File::open("cert.pem").unwrap());
let key_file = &mut BufReader::new(File::open("key.pem").unwrap());
let cert_chain = rustls_pemfile::certs(cert_file).unwrap();
let mut keys = rustls_pemfile::pkcs8_private_keys(key_file).unwrap();
let server_config = ServerConfig::builder()
.with_safe_defaults() // Enforces TLS 1.2+ and strong ciphers
.with_no_client_auth() // Adjust if mutual TLS is needed
.with_single_cert(cert_chain, keys.remove(0))
.unwrap();
HttpServer::new(|| {
App::new().route("/", web::get().to(index))
})
.bind_rustls("0.0.0.0:8443", server_config)?
.run()
.await
}Key points:
.with_safe_defaults()usesrustls's secure preset (TLS 1.2/1.3, AEAD ciphers only). Avoid.with_protocol_versions(&[&Protocol::TLSv1_2, &Protocol::TLSv1_3])for explicit control.- Do not use
.with_cipher_suites(...)to re-enable CBC-mode suites; the safe default excludes them.
2. Enforce HTTPS and HSTS
Use Actix middleware to redirect HTTP and set HSTS:
use actix_web::{dev::Service, http::header, HttpResponse, HttpMessage};
use actix_web::middleware::{self, Redirect, DefaultHeaders};
let app = App::new()
.wrap(Redirect::new().to("https://{host}{uri}")) // HTTP to HTTPS
.wrap(DefaultHeaders::new()
.header(header::STRICT_TRANSPORT_SECURITY, "max-age=31536000; includeSubDomains"))
.service(web::resource("/").route(web::get().to(index)));This ensures clients never communicate over HTTP and instruct browsers to always use HTTPS.
3. Secure Outbound Calls
If your Actix service calls external APIs, configure the client with strict certificate verification. For reqwest:
let client = reqwest::Client::builder()
.use_rustls_tls() // Use rustls with default secure config
.build()
.unwrap();
// Never call .danger_accept_invalid_certs(true) in production4. Validate Redirects
When generating redirects, whitelist allowed schemes and domains:
fn safe_redirect(url: &str) -> HttpResponse {
if url.starts_with("https://trusted-api.example.com") {
HttpResponse::Found().append_header(("location", url)).finish()
} else {
HttpResponse::BadRequest().body("Invalid redirect URL")
}
}By combining these Actix-specific configurations, you close common MITM vectors. Continuously monitor your API's TLS posture with middleBrick's Dashboard to track score improvements over time and receive alerts if a regression introduces weak ciphers or disables HSTS.
FAQ
Q: Does MITM only affect public APIs?
A: No. Internal or partner APIs are equally vulnerable if TLS is misconfigured. Attackers on the same network (e.g., compromised internal host, malicious insider) can intercept traffic. All Actix APIs, regardless of exposure, must enforce strong TLS.
Q: Can middleBrick detect all TLS flaws in my Actix API?
A: middleBrick's Encryption check tests for common misconfigurations (protocol versions, cipher strength, certificate issues, HSTS, HTTP fallback). It does not scan for every CVE in underlying TLS libraries (e.g., a specific rustls memory corruption bug). For those, you must keep dependencies updated via cargo audit. middleBrick's score reflects the observable security posture from the network perspective.