HIGH crlf injectionaxumrust

Crlf Injection in Axum (Rust)

Crlf Injection in Axum with Rust — how this specific combination creates or exposes the vulnerability

Crlf Injection occurs when an attacker can inject carriage return (CR, \r) and line feed (\n) characters into HTTP headers or the response body, causing header injection or response splitting. In Axum with Rust, this typically arises when user-controlled input is reflected into headers such as Location, Content-Type, or custom headers without proper sanitization. Axum’s extractor and response builder APIs allow developers to construct responses dynamically; if user data is passed directly into header values, an attacker can supply \r\n sequences to inject additional headers or break out of the message body into a new response.

For example, an endpoint that redirects based on a user-supplied `next` parameter can be abused if the parameter contains \r\n. An input like https://example.com\r\nSet-Cookie: malicious=1 can lead to header injection, causing the client to receive an unintended Set-Cookie header. Axum’s middleware and routing layer do not inherently sanitize inputs for header context; the responsibility falls on the developer to validate and encode any user-controlled data before it reaches the response builder. Because Axum is built on Hyper and relies on safe Rust abstractions, the language’s type system does not prevent logical errors where malformed data is passed to header setters, making application-layer validation essential.

This vulnerability maps to the OWASP API Top 10 category '2023-A1: Broken Object Level Authorization' when combined with BOLA/IDOR patterns, and it can also facilitate HTTP response splitting, which is relevant to the 'Data Exposure' and 'Input Validation' checks performed by middleBrick. The scanner tests whether injected CRLF sequences result in unexpected headers or body splits, reporting findings with severity and remediation guidance. Properly validating and encoding newlines in user input mitigates the risk and ensures compliance with secure coding practices.

Rust-Specific Remediation in Axum — concrete code fixes

To prevent Crlf Injection in Axum, you must sanitize user-controlled data before using it in headers or the response body. The safest approach is to reject or encode CR and LF characters in any input that may become a header value or part of the status message. Below are concrete Rust examples demonstrating secure handling within an Axum handler.

First, define a helper to reject disallowed characters for header-safe strings:

/// Rejects characters that could lead to header or response splitting.
fn is_header_safe(value: &str) -> bool {
    !value.contains('\r') && !value.contains('\n')
}

/// Validates a redirect target to prevent CRLF injection.
fn validate_redirect_target(url: &str) -> Result<(), String> {
    if !is_header_safe(url) {
        return Err("Invalid characters in redirect target".to_string());
    }
    // Optional: enforce a strict allowlist or URL validation
    if url.starts_with("http://") || url.starts_with("https://") {
        Ok(())
    } else {
        Err("Redirect target must be an absolute HTTP(S) URL".to_string())
    }
}

Use this validator in an Axum handler that performs redirects:

use axum::{
    extract::Query,
    response::{IntoResponse, Redirect},
};
use std::net::SocketAddr;
use axum::routing::get;
use axum::Router;

async fn redirect_handler(
    Query(params): Query<std::collections::HashMap<String, String>>
) -> Result<impl IntoResponse, (axum::http::StatusCode, String)> {
    let target = params.get("next").ok_or_else(|| {
        (axum::http::StatusCode::BAD_REQUEST, "Missing 'next' parameter".to_string())
    })?;
    validate_redirect_target(target)?;
    Ok(Redirect::found(target))
}

#[tokio::main]
async fn main() {
    let app = Router::new().route("/redirect", get(redirect_handler));
    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();
}

For custom headers, avoid direct concatenation with user input. Instead, use Axum’s typed header types or explicitly encode newlines:

use axum::{
    async_trait,
    extract::Extension,
    headers::{HeaderMap, HeaderValue, InvalidHeaderValue},
    response::Response,
};
use std::convert::TryFrom;

fn set_safe_header(mut response: Response, value: &str) -> Result<Response, InvalidHeaderValue> {
    let sanitized: String = value.chars().filter(|&c| c != '\r' && c != '\n').collect();
    let header_value = HeaderValue::from_str(&sanitized)?;
    response.headers_mut().insert("X-Custom-Reason", header_value);
    Ok(response)
}

These patterns ensure that CR and LF characters cannot alter the structure of HTTP messages, effectively mitigating Crlf Injection in Axum services. When combined with middleBrick’s checks for Input Validation and Data Exposure, you can verify that your implementation correctly handles edge cases and adheres to secure coding standards.

Frequently Asked Questions

Can an attacker exploit CRLF Injection without direct user input in Axum?
Yes, if any part of the request (such as cookies, query parameters, or headers processed by middleware) is reflected into response headers without validation, CRLF Injection can occur. Always treat all incoming data as untrusted and sanitize before using it in header construction.
Does middleBrick detect CRLF Injection in Axum APIs?
Yes, middleBrick’s Input Validation and Data Exposure checks include tests for CRLF injection sequences. Findings include severity and remediation guidance to help you address the issue in Rust-based Axum services.