Missing Tls in Actix
How Missing TLS Manifests in Actix
Missing TLS in Actix applications creates a critical attack surface where sensitive data travels in plaintext across networks. In Actix, this vulnerability often appears when developers use HttpServer::new without HTTPS configuration, exposing API endpoints to eavesdropping, man-in-the-middle attacks, and credential theft.
The most common manifestation occurs when Actix applications are deployed behind reverse proxies without proper TLS termination verification. Attackers can intercept traffic between the proxy and Actix server, capturing authentication tokens, API keys, and personal data. This is particularly dangerous when Actix handles financial transactions, healthcare data, or any PII subject to compliance requirements.
Actix-specific code patterns that enable this vulnerability include:
use actix_web::{web, App, HttpServer, HttpResponse};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(web::resource("/api/*").to(handle_api))
})
.bind("127.0.0.1:8080")? // Plain HTTP - vulnerable!
.run()
.await
}
Another Actix-specific scenario involves TLS certificate misconfiguration. Developers might enable HTTPS but use self-signed certificates or weak cipher suites, creating a false sense of security while still exposing data to sophisticated attackers who can exploit cryptographic weaknesses.
API endpoints that accept sensitive parameters without TLS become prime targets. Consider an Actix endpoint handling password resets or payment processing:
#[post("/reset-password")]
async fn reset_password(
creds: web::Json,
data: web::Data
) -> Result {
// Password reset logic - but transmitted over HTTP!
let result = data.service.reset_password(creds.username, creds.password);
Ok(HttpResponse::Ok().json(result))
}
Without TLS, attackers can capture these credentials in transit, leading to account takeover and data breaches. The Actix framework itself doesn't enforce TLS, making it the developer's responsibility to implement proper encryption.
Actix-Specific Detection
Detecting missing TLS in Actix applications requires both manual inspection and automated scanning. The first step is examining the HttpServer::bind calls in your Actix codebase. Look for patterns binding to HTTP ports (80, 8080) instead of HTTPS ports (443, 8443).
middleBrick provides Actix-specific TLS detection through its black-box scanning approach. The scanner tests your Actix API endpoints for:
- HTTP response on standard ports (80, 8080)
- Missing TLS certificate chains
- Weak TLS configurations if HTTPS is enabled
- Mixed content vulnerabilities where HTTPS pages load HTTP resources
The CLI tool makes Actix TLS scanning straightforward:
npx middlebrick scan https://your-actix-api.com/api
middleBrick's scanning engine tests the unauthenticated attack surface, identifying endpoints that accept connections without TLS. The scanner provides a security risk score and specific findings about missing TLS protection, helping Actix developers understand their exposure level.
For development environments, middleBrick's GitHub Action can automatically scan Actix APIs before deployment:
name: API Security Scan
on: [push, pull_request]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run middleBrick Scan
run: |
npx middlebrick scan https://staging.your-actix-app.com/api
continue-on-error: true
The scanner also analyzes OpenAPI specifications for Actix applications, cross-referencing documented endpoints with actual TLS implementations to identify discrepancies between design and runtime security posture.
Actix-Specific Remediation
Securing Actix applications against missing TLS requires implementing proper HTTPS configuration. The primary approach uses Rust's native-tls or rustls crates with Actix's TLS support:
use actix_web::{web, App, HttpServer, HttpResponse};
use rustls::{NoClientAuth, ServerConfig};
use rustls::internal::pemfile::{certs, rsa_private_keys};
use std::fs::File;
use std::io::BufReader;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// Load TLS certificates
let cert_file = &mut BufReader::new(File::open("cert.pem")?);
let key_file = &mut BufReader::new(File::open("key.pem")?);
let cert_chain = certs(cert_file).unwrap();
let mut keys = rsa_private_keys(key_file).unwrap();
let config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_certificates(cert_chain, keys.remove(0)));
HttpServer::new(|| {
App::new()
.service(web::resource("/api/*").to(handle_api))
})
.bind_rustls("0.0.0.0:443", config)? // Secure HTTPS
.run()
.await
}
For production deployments, Actix developers should implement TLS certificate management through environment variables and secret management systems. Here's a more robust approach:
use actix_web::{web, App, HttpServer, HttpResponse};
use rustls::ServerConfig;
use std::io::BufReader;
use std::env;
async fn init_tls() -> Result {
let cert_path = env::var("TLS_CERT_PATH").unwrap_or("cert.pem".to_string());
let key_path = env::var("TLS_KEY_PATH").unwrap_or("key.pem".to_string());
let cert_file = &mut BufReader::new(File::open(cert_path)?);
let key_file = &mut BufReader::new(File::open(key_path)?);
let cert_chain = certs(cert_file).unwrap();
let mut keys = rsa_private_keys(key_file).unwrap();
ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_certificates(cert_chain, keys.remove(0))
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let tls_config = init_tls().await.unwrap();
HttpServer::new(|| {
App::new()
.service(web::resource("/api/*").to(handle_api))
})
.bind_rustls("0.0.0.0:443", tls_config)?
.run()
.await
}
For development environments, Actix supports HTTP-to-HTTPS reverse proxy configurations. Using tools like Nginx or Caddy in front of Actix provides TLS termination while maintaining development simplicity:
use actix_web::{web, App, HttpServer, HttpResponse};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(web::resource("/api/*").to(handle_api))
})
.bind("127.0.0.1:8080")? // HTTP for proxy
.run()
.await
}
This configuration requires proper X-Forwarded-Proto header handling in Actix to ensure the application recognizes HTTPS requests correctly when behind a proxy.
Related CWEs: encryption
| CWE ID | Name | Severity |
|---|---|---|
| CWE-319 | Cleartext Transmission of Sensitive Information | HIGH |
| CWE-295 | Improper Certificate Validation | HIGH |
| CWE-326 | Inadequate Encryption Strength | HIGH |
| CWE-327 | Use of a Broken or Risky Cryptographic Algorithm | HIGH |
| CWE-328 | Use of Weak Hash | HIGH |
| CWE-330 | Use of Insufficiently Random Values | HIGH |
| CWE-338 | Use of Cryptographically Weak PRNG | MEDIUM |
| CWE-693 | Protection Mechanism Failure | MEDIUM |
| CWE-757 | Selection of Less-Secure Algorithm During Negotiation | HIGH |
| CWE-261 | Weak Encoding for Password | HIGH |