Path Traversal in Actix with Basic Auth
Path Traversal in Actix with Basic Auth — how this specific combination creates or exposes the vulnerability
Path Traversal occurs when user-controlled input used in file paths is not properly validated, allowing an attacker to read or write files outside the intended directory by using sequences like ../. In Actix web applications, this often manifests through endpoints that build file system paths from request parameters, query strings, or headers without sufficient sanitization.
When Basic Auth is used, the Authorization header is typically parsed by Actix middleware or custom guards before reaching the handler. While authentication itself does not introduce the traversal, it can affect how findings are reported during scans. middleBrick tests unauthenticated attack surfaces; if the endpoint is protected only by Basic Auth and no authentication is supplied, middleBrick will flag the path as unauthenticated and note the authentication requirement in findings. If authentication is supplied, middleBrick can test whether a valid credential pair changes the behavior or exposure of path traversal-prone routes. In practice, the vulnerability depends on how paths are constructed in handlers, not on the presence of Basic Auth, but authentication context influences scan coverage and reported risk.
For example, an Actix handler that reads a user profile image based on a query parameter without sanitization could be exploited as follows: a request to /files?name=../../../etc/passwd may return sensitive system files. If Basic Auth is enforced via an extractor like actix_http::HttpMessage::identity or a custom guard, the request must include a valid header; an invalid or missing credential results in a 401, which may mask traversal behavior during manual testing. middleBrick’s authentication check flags whether the endpoint leaks information without auth and whether authenticated access changes file exposure, helping to identify insecure path handling behind auth gates.
Common root causes in Actix include:
- Concatenating user input directly to a base directory string.
- Using path components from headers or cookies to locate files.
- Relying on framework defaults that do not normalize or restrict
..sequences.
Because Actix does not inherently sanitize paths, developers must validate and sanitize inputs explicitly. middleBrick’s property authorization and input validation checks help surface these weaknesses by probing endpoints with traversal payloads under different authentication states and mapping findings to OWASP API Top 10 and other compliance frameworks.
Basic Auth-Specific Remediation in Actix — concrete code fixes
Remediation focuses on strict input validation, path normalization, and avoiding direct use of user input in filesystem operations. Below are concrete Actix examples that demonstrate secure handling when Basic Auth is in use.
1. Basic Auth setup with Actix guards
Use Actix's built-in Basic Auth extractor to enforce authentication before reaching sensitive handlers. This ensures only identified users can invoke the endpoint, but you must still secure the path logic.
use actix_web::{web, App, HttpResponse, HttpServer, guard};
use actix_web::http::header::HeaderValue;
use actix_web::dev::ServiceRequest;
use actix_web::error::ErrorUnauthorized;
use std::future::{ready, Ready};
fn validate_credentials(req: ServiceRequest) -> Result {
// Expecting "Authorization: Basic base64(credentials)"
if let Some(auth_header) = req.headers().get("Authorization") {
if let Ok(auth_str) = auth_header.to_str() {
if auth_str.starts_with("Basic ") {
// In production, decode and validate against a store
return ready(Ok(req)).into();
}
}
}
Err((ErrorUnauthorized("Unauthorized"), req))
}
async fn profile_image(path: web::Query>) -> HttpResponse {
// Unsafe usage — do not use
let filename = path.get("name").unwrap_or(&"default.png".to_string());
let full_path = format!("/var/www/uploads/{}", filename);
match std::fs::read(&full_path) {
Ok(bytes) => HttpResponse::Ok().body(bytes),
Err(_) => HttpResponse::NotFound().finish(),
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.service(
web::resource("/profile/image")
.guard(guard::Header("Authorization", HeaderValue::from_static("Basic dXNlcjpwYXNz")))
.to(profile_image),
)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
The above illustrates a guard that checks for a Basic Auth header. However, the handler profile_image remains unsafe because it directly concatenates user input into a path.
2. Secure path handling with sanitization and base directory restriction
Use Rust’s std::path::Path utilities to clean and validate paths. Always resolve against a known base directory and ensure the final path remains within that directory.
use actix_web::web;
use std::path::{Path, PathBuf};
fn safe_path(user_input: &str, base_dir: &Path) -> Option {
// Normalize and join; strip leading components that could escape
let requested = Path::new(user_input);
let mut final_path = base_dir.to_path_buf();
for component in requested.components() {
match component {
std::path::Component::Normal(segment) => final_path.push(segment),
// Explicitly reject parent directory attempts
std::path::Component::ParentDir => return None,
_ => return None, // Reject other unsafe components
}
}
Some(final_path)
}
async fn secure_profile_image(path: web::Query>) -> HttpResponse {
let base_dir = Path::new("/var/www/uploads");
let input = match path.get("name") {
Some(v) => v,
None => return HttpResponse::BadRequest().body("missing name"),
};
match safe_path(input, base_dir) {
Some(full_path) => {
if full_path.exists() {
match std::fs::read(&full_path) {
Ok(bytes) => HttpResponse::Ok().body(bytes),
Err(_) => HttpResponse::InternalServerError().finish(),
}
} else {
HttpResponse::NotFound().body("file not found")
}
}
None => HttpResponse::BadRequest().body("invalid path"),
}
}
This approach ensures that even if an attacker sends ../../../etc/passwd, the ParentDir component causes a rejection, and the final path remains under /var/www/uploads. Combine this with Basic Auth guards to control access, and use middleBrick’s CLI to verify that the endpoint no longer exposes traversal risks under authenticated and unauthenticated probes.
Additional recommendations:
- Avoid using headers or cookies to derive filesystem paths.
- Apply principle of least privilege to the runtime process’s filesystem access.
- Use middleBrick’s input validation and property authorization checks to confirm that traversal payloads are handled safely across authentication states.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |