HIGH crlf injectionrocketbasic auth

Crlf Injection in Rocket with Basic Auth

Crlf Injection in Rocket with Basic Auth — how this specific combination creates or exposes the vulnerability

Crlf Injection occurs when user-controlled data is reflected in HTTP headers without sanitization, allowing an attacker to inject additional header lines such as \r\n (Carriage Return + Line Feed). In the Rocket web framework for Rust, this typically arises when header values are constructed from request parameters or other unchecked inputs. When Basic Authentication is used, the Authorization header is parsed by Rocket, but if application code extracts credentials (for example the username or password) and then uses that data to build custom response headers, the risk of header injection emerges.

Consider a scenario where an endpoint reads the Authorization header, decodes the Base64 credentials, and then echoes part of the credential into a custom header such as X-User. An attacker can supply a password containing \r\n sequences to split the header chain, injecting new headers like X-Injected: true or even smuggled request lines that affect downstream proxies or caches. Because Rocket validates the presence of Basic Auth but does not inherently restrict the content of the decoded payload, the developer must treat any credential-derived data as untrusted input.

In a black-box scan, middleBrick checks for Crlf Injection by submitting crafted inputs that include \r\n and sequences like %0d%0a in parameters and headers, then observing whether those sequences appear verbatim in response headers. When combined with Basic Auth, the scanner tests whether authentication material can be used to smuggle headers. This is relevant for unauthenticated attack surface testing because the endpoint may be accessible without credentials, yet the logic that processes Basic Auth can still be triggered via the presence of the header. The framework’s OpenAPI/Swagger spec analysis (2.0, 3.0, 3.1) with full $ref resolution can highlight which endpoints declare the Authorization header, helping to prioritize testing of those routes.

Real-world attack patterns mirror classic HTTP response splitting and header injection issues cataloged in the OWASP API Security Top 10. For example, an injected header like Set-Cookie: session=attacker could facilitate session fixation if the application later uses the injected data to set cookies. Similarly, smuggling via Transfer-Encoding or Content-Length can occur when proxies or load balancers process the manipulated chain. Because Rocket does not sanitize header values derived from credentials, the onus is on the developer to validate and encode any user-influenced data before it reaches the header layer.

middleBrick’s LLM/AI Security checks do not directly test Crlf Injection, but the scanner’s parallel checks include Input Validation and Data Exposure, which help surface places where header logic may be insufficiently constrained. By correlating runtime findings with spec definitions, the tool can point to endpoints where Basic Auth is declared but header construction is not properly constrained, guiding focused manual review and testing.

Basic Auth-Specific Remediation in Rocket — concrete code fixes

Remediation focuses on two areas: strict validation of any data derived from credentials before it is used in headers, and safe construction of response headers using frameworks that prevent line breaks from being interpreted as delimiter boundaries.

First, avoid directly inserting credential data into headers. If you need to log or forward a username, sanitize it by removing or encoding \r and \n characters. For instance, replace newlines and carriage returns with a safe placeholder or strip them entirely. In Rocket, you can implement a helper that ensures no line breaks are present before using the string in any header.

use rocket::http::Header; // Rocket 0.5+ style example

fn safe_header_value(input: &str) -> String {
    input.chars().filter(|&c| c != '\r' && c != '\n').collect()
}

#[rocket::get("/profile")]
async fn profile(authorization: rocket::http::Header<'>) -> String {
    if let Some(auth_header) = authorization.to_str().ok() {
        // Example: "Basic base64string"
        if auth_header.starts_with("Basic ") {
            let encoded = auth_header.trim_start_matches("Basic ");
            // Decode credentials (use a proper base64 crate in production)
            if let Ok(decoded) = general_purpose::STANDARD.decode(encoded) {
                if let Ok(credentials) = String::from_utf8(decoded) {
                    let parts: Vec&lt;_&gt; = credentials.split(':').collect();
                    if parts.len() == 2 {
                        let username = safe_header_value(parts[0]);
                        // Use sanitized username in a response header safely
                        return format!("User: {}", username);
                    }
                }
            }
        }
    }
    String::from("Unauthorized")
}

Second, prefer structured data over concatenated header values. Instead of building a header like X-User: {username}\r\nX-Other: value, use Rocket’s header management APIs that handle line separation internally. If you must set custom headers, ensure that each header is set individually rather than concatenated, and never allow raw user input to contain \r or \n.

#[rocket::get("/user")]
async fn user_info(authorization: rocket::http::Header<'>) -> (rocket::http::Status, rocket::http::Header) {
    if let Some(auth) = authorization.to_str().ok().filter(|s| s.starts_with("Basic ")) {
        let payload = general_purpose::STANDARD.decode(&auth[6..]).ok()?;
        if let Ok(creds) = String::from_utf8(payload) {
            let mut parts = creds.splitn(2, ':');
            if let (Some(user), Some(_pass)) = (parts.next(), parts.next()) {
                let safe_user = user.replace(|c: char| c == '\r' || c == '\n', "_");
                // Set one header safely; Rocket ensures proper formatting
                let header = rocket::http::Header::new("X-Safe-User", safe_user);
                return (rocket::http::Status::Ok, header);
            }
        }
    }
    (rocket::http::Status::Unauthorized, rocket::http::Header::new("X-Error", "invalid"))
}

Additionally, consider moving away from Basic Auth for sensitive endpoints in favor of token-based authentication, which avoids the need to parse and re-use credentials in headers. If Basic Auth is required, ensure TLS is enforced to protect credentials in transit and apply rigorous input validation on any part of the credentials that your application logic uses.

When integrating with CI/CD, the middleBrick GitHub Action can be configured with a threshold to fail builds if a Crlf Injection finding appears, helping to prevent insecure patterns from reaching production. The CLI allows quick local scans with middlebrick scan <url> to validate fixes before committing changes.

Frequently Asked Questions

Can Crlf Injection occur if the Authorization header itself is not user-controlled?
Yes. Even when the Authorization header is present and valid, if your Rocket code extracts credentials (e.g., the password) and places that data into other response headers without sanitization, an attacker can control the password and inject \r\n sequences. The vulnerability lies in how derived credential data is used, not merely in the presence of Basic Auth.
Does middleBrick fix Crlf Injection findings automatically?
No. middleBrick detects and reports Crlf Injection with severity and remediation guidance, but it does not patch or block. Developers must apply the recommended sanitization and header handling fixes in the Rocket application code.