Request Smuggling in Actix
How Request Smuggling Manifests in Actix
Request smuggling in Actix typically occurs when HTTP request parsing boundaries become ambiguous between Actix and upstream proxies or load balancers. The vulnerability arises when Actix's request parsing differs from the parsing logic of intermediary systems, creating scenarios where one system interprets the request body differently than another.
In Actix applications, this often manifests through Content-Length and Transfer-Encoding header conflicts. When a client sends a request with both headers present, Actix's default behavior can lead to ambiguous parsing. For example, if a proxy forwards a request with Content-Length: 10 but the actual body contains more data, Actix might read the extra bytes as belonging to the current request when they should belong to the next one.
Actix's streaming request handling can also create smuggling opportunities. When using Payload directly or implementing custom Stream handlers, developers might inadvertently create parsing gaps. Consider this vulnerable pattern:
async fn handle_request(mut payload: Payload) -> impl Responder { let mut body = BytesMut::new(); while let Some(chunk) = payload.next().await { body.extend_from_slice(&chunk.unwrap()); } // Process body } The issue here is that Actix doesn't enforce strict Content-Length validation by default. If an attacker sends a request with Content-Length: 5 but provides 15 bytes of data, the remaining 10 bytes could be interpreted as the start of the next request by Actix, while the proxy might have already parsed it differently.
Another Actix-specific manifestation occurs with multipart form handling. When using actix-multipart, improper boundary handling can lead to smuggling if the multipart parser doesn't strictly validate content lengths against the overall request size. This becomes particularly dangerous when Actix is behind a reverse proxy that terminates TLS and re-sends requests.
CL.TE (Content-Length header, Transfer-Encoding body) and TE.CL (Transfer-Encoding header, Content-Length body) vulnerabilities are especially relevant to Actix applications. The framework's default configuration might not properly validate these header combinations, allowing attackers to craft requests that different systems parse inconsistently.
Actix-Specific Detection
Detecting request smuggling in Actix applications requires both manual testing and automated scanning. For manual detection, start by examining your Actix application's request parsing logic. Look for places where you directly handle Payload or implement custom streaming logic without strict Content-Length validation.
A practical detection method involves sending requests with conflicting Content-Length and Transfer-Encoding headers to your Actix endpoints. For example:
POST /api/v1/resource HTTP/1.1 Host: example.com Content-Length: 6 Transfer-Encoding: chunked 0
POST /api/v1/secret HTTP/1.1 Host: example.com Content-Length: 15 X-CSRF-Token: valid X-Admin: trueIf Actix processes both requests as a single payload, you've identified a smuggling vulnerability. The key is to observe whether Actix's parsing aligns with your proxy's parsing.
For automated detection, middleBrick's API security scanner includes specific checks for request smuggling vulnerabilities in Actix applications. The scanner tests for ambiguous Content-Length and Transfer-Encoding combinations, evaluates streaming request handling, and checks multipart form parsing boundaries. Since middleBrick performs black-box scanning, it doesn't require access to your source code—just the running API endpoint.
middleBrick's detection methodology includes sending carefully crafted requests that test the boundaries between Actix's parser and common proxy configurations. The scanner specifically looks for discrepancies in how Actix and upstream systems interpret request boundaries, which is the core mechanism of request smuggling.
Another detection approach involves using middleBrick's continuous monitoring feature (Pro plan). By regularly scanning your Actix API endpoints, you can identify when configuration changes or deployments introduce new smuggling vulnerabilities. The scanner provides severity ratings and specific remediation guidance tailored to Actix's architecture.
For development environments, the middleBrick CLI tool allows you to scan Actix applications during development. Simply run middlebrick scan http://localhost:8080 to check for request smuggling and other API security issues before deployment.
Actix-Specific Remediation
Remediating request smuggling in Actix applications requires a multi-layered approach. The first and most critical step is implementing strict Content-Length validation. Actix provides the ContentLengthLimit middleware that can be used to enforce maximum request sizes and validate content lengths:
use actix_web::{middleware, App, HttpServer}; use actix_web::middleware::ContentLengthLimit; #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .wrap(ContentLengthLimit::default()) // Set default limit .wrap(middleware::NormalizePath) .service(your_service) }) .bind("127.0.0.1:8080")? .run() .await } For more granular control, you can implement custom middleware that validates Content-Length against the actual payload size. This ensures that Actix doesn't process requests where the declared length doesn't match the received data:
use actix_web::{dev::Payload, http::header, middleware::Middleware, Error, HttpResponse}; struct ContentLengthValidator; impl Middleware for ContentLengthValidator { async fn call(&self, req: actix_web::HttpRequest, payload: &mut Payload) -> Result<actix_web::dev::ServiceRequest, Error> { if let Some(len) = req.headers().get(header::CONTENT_LENGTH) { let len = len.to_str()?.parse::()?; // Validate length against actual payload size // Implementation depends on your payload handling } Ok(ServiceRequest::new(req, payload)) } } When using multipart forms with actix-multipart, ensure you validate the overall Content-Length against the sum of all parts. The library provides MultipartError::Overflow for handling oversized payloads:
use actix_multipart::Multipart; async fn upload(mut payload: Multipart) -> impl Responder { let mut total_size = 0; while let Ok(Some(mut field)) = payload.try_next().await { let content_type = field.content_disposition().unwrap(); let size = field.text().await.unwrap().len(); total_size += size; if total_size > MAX_UPLOAD_SIZE { return HttpResponse::PayloadTooLarge().finish(); } } HttpResponse::Ok().finish() } For applications behind reverse proxies, configure your Actix application to trust the proxy's headers using the Forwarded middleware. This ensures consistent parsing between Actix and the proxy:
use actix_web::middleware::Forwarded; App::new() .wrap(Forwarded::default()) .wrap(ContentLengthLimit::default()) .service(your_service)Finally, implement comprehensive logging of request headers and sizes. This helps detect smuggling attempts in production and provides audit trails for compliance requirements. middleBrick's compliance reports can help map your Actix application's security posture to standards like PCI-DSS and SOC2, which require detailed logging of security-relevant events.
Frequently Asked Questions
How does request smuggling differ in Actix compared to other Rust frameworks?
Payload and custom stream handling requires developers to be more vigilant about implementing proper validation.