HIGH crlf injectionaxumbasic auth

Crlf Injection in Axum with Basic Auth

Crlf Injection in Axum with Basic Auth — 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 a header or status-line value. In Axum, this typically arises when user-controlled data is reflected in HTTP response headers without sanitization. When Basic Authentication is used, the Authorization header is parsed by Axum middleware or handlers, and parts of it (such as the username or password) may be echoed into downstream headers or logs. If these values are not validated and an attacker supplies \r\n in the credentials, injected content can break header parsing and enable header manipulation or response splitting.

Consider an Axum handler that reads the Basic Auth token, decodes it, and then includes the username in a custom response header for debugging or correlation purposes:

use axum::{
    async_trait,
    extract::Request,
    response::Response,
    routing::get,
    Router,
};
use std::convert::Infallible;

async fn auth_handler(
    auth: Option<axum::extract::auth::Authorization<axum::http::header::authorization::Basic>>
) -> Response {
    let username = auth.map(|a| a.into_username()).unwrap_or_else(|| "anonymous".to_string());
    // Dangerous: username may contain \r\n if input is maliciously crafted
    let mut response = Response::new(axum::body::Body::from("ok"));
    response.headers_mut().insert(
        "X-User",
        username.parse().unwrap_or_else(|_| "unknown".parse().unwrap()),
    );
    response
}

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(auth_handler));
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

If an attacker sends a request like Authorization: Basic dGVzdDpcIn0= (which decodes to test:" with crafted line breaks in the raw credential), and the server reflects the username in a header without validation, the injected \r\n can split the header stream. This may enable injection of arbitrary headers, potentially aiding cache poisoning, HTTP response splitting, or misleading logging. In a security scan, such patterns are flagged under HTTP Smuggling, Header Manipulation, and Input Validation categories, and the findings map to OWASP API Top 10 and CWE-113 (Improper Neutralization of CR and LF.)

Note that Axum does not automatically sanitize inputs from Basic Auth; developers must treat these values as untrusted. Even when using middleware for authentication, reflected credentials or parsed fields should be validated against a strict allowlist and encoded before being placed in headers, cookies, or any other protocol-sensitive context.

Basic Auth-Specific Remediation in Axum — concrete code fixes

Remediation focuses on never reflecting untrusted data into protocol-sensitive locations and strictly validating inputs from Basic Auth. If you must include a value in a header, ensure it is sanitized, and prefer using opaque tokens or session identifiers instead of raw credentials.

Below are concrete Axum examples that demonstrate safe handling of Basic Auth credentials.

1) Reject or sanitize carriage returns and line feeds

Validate the decoded username and password before use. Reject or sanitize characters such as \r and \n.

use axum::{
    async_trait,
    extract::Request,
    response::Response,
    routing::get,
    Router,
};
use std::convert::Infallible;

fn sanitize_header_value(value: &str) -> Option<String> {
    if value.contains('\r') || value.contains('\n') {
        return None;
    }
    Some(value.to_string())
}

async fn safe_auth_handler(
    auth: Option<axum::extract::auth::Authorization<axum::http::header::authorization::Basic>>
) -> Response {
    let username = auth
        .map(|a| a.into_username())
        .and_then(|u| sanitize_header_value(&u).map(|s| s.into()))
        .unwrap_or_else(|| "anonymous".to_string());

    let mut response = Response::new(axum::body::Body::from("ok"));
    if let Some(val) = sanitize_header_value(&username) {
        response.headers_mut().insert("X-User", val.parse().unwrap_or_else(|_| "unknown".parse().unwrap()));
    }
    response
}

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(safe_auth_handler));
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

2) Avoid reflecting credentials in headers; use a session or token instead

Do not place raw Basic Auth fields into headers. If you need a user identifier for logging or tracing, generate a separate, safe value.

use axum::{
    async_trait,
    extract::Request,
    response::Response,
    routing::get,
    Router,
};
use std::convert::Infallible;
use uuid::Uuid;

async fn token_based_handler(
    auth: Option<axum::extract::auth::Authorization<axum::http::header::authorization::Basic>>
) -> Response {
    let _credentials_verified = auth.is_some(); // perform verification as needed
    let trace_id = Uuid::new_v4().to_string();
    let mut response = Response::new(axum::body::Body::from("ok"));
    response.headers_mut().insert(
        "X-Trace-Id",
        trace_id.parse().unwrap_or_else(|_| "unknown".parse().unwrap()),
    );
    response
}

#[tokio::main]
async fn main() {
    let app = Router::new().route("/", get(token_based_handler));
    axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
        .serve(app.into_make_service())
        .await
        .unwrap();
}

These patterns reduce the risk of response splitting and header injection. For broader protection, combine input validation with a defense-in-depth approach that includes strict Content-Security-Policy and careful logging practices.

Frequently Asked Questions

Can middleBrick detect Crlf Injection in Axum with Basic Auth?
Yes. middleBrick scans unauthenticated attack surfaces and includes HTTP Smuggling and Input Validation checks that can identify Crlf Injection risks when user-controlled data is reflected in headers.
Does middleBrick provide fixes for Crlf Injection?
middleBrick detects and reports findings with remediation guidance. It does not fix, patch, block, or remediate issues; developers should apply the suggested sanitization and avoid reflecting untrusted credentials in headers.