MEDIUM log injectionaxumbasic auth

Log Injection in Axum with Basic Auth

Log Injection in Axum with Basic Auth — how this specific combination creates or exposes the vulnerability

Log injection occurs when untrusted input is written directly into log entries without sanitization, enabling log forging or log poisoning. In Axum applications that use HTTP Basic Authentication, combining credential handling with logging creates a concrete risk. When a handler parses the Authorization header, extracts the username and password, and then logs values such as username or decision outcomes like "authentication failed" without validation, an attacker can inject newline characters or structured tokens into the log stream.

For example, an attacker could send an Authorization header containing a username like admin\nAuthorization: Basic [credentials]. If the application logs the username verbatim, the forged line can appear as a separate, authoritative log entry, complicating audit analysis. In Axum, this typically arises in two places: (1) during filter execution where authentication state is logged, and (2) in custom logging layers or middleware that record request identifiers alongside credentials-derived context. Because Basic Auth credentials are often base64-encoded in transit but decoded server-side before any logging, the decoded username becomes a direct injection vector if not constrained.

The risk is compounded when logs are aggregated into monitoring or SIEM systems, where newline injection can break log parsers, cause misattribution of events, or facilitate injection into log-based alerting logic. Although Axum itself does not add extra formatting around logs, application code that uses macros like info! or error! with user-controlled strings is susceptible. An attacker may not directly alter application behavior via log injection in Axum, but they can obscure real events, trigger alert fatigue, or provide pivot data for correlated attacks. This specific combination—Basic Auth for access control plus unchecked logging—exemplifies how authentication context can unintentionally amplify injection surfaces.

Basic Auth-Specific Remediation in Axum — concrete code fixes

Remediation focuses on sanitizing any data derived from the Authorization header before it reaches logging statements. Do not log raw usernames or passwords; instead, log normalized, constrained identifiers or hashes. Validate the username against an allowlist or regex before using it in log messages, and ensure that any string interpolation within logging macros is explicitly escaped or omitted.

Below are two Axum handler patterns: one vulnerable and one remediated.

// Vulnerable example: logging raw username from Basic Auth
use axum::{routing::get, Router, extract::Request};
use std::convert::Infallible;

async fn handler(
    request: Request,
) -> Result {
    if let Some(auth_header) = request.headers().get("authorization") {
        if let Ok(auth_str) = auth_header.to_str() {
            if auth_str.starts_with("Basic ") {
                let encoded = auth_str.strip_prefix("Basic ").unwrap_or("");
                // naive decoding for illustration only
                if let Ok(decoded) = base64::decode(encoded) {
                    if let Ok(credentials) = String::from_utf8(decoded) {
                        let parts: Vec<&str> = credentials.splitn(2, ':').collect();
                        if parts.len() == 2 {
                            let (username, _password) = (parts[0], parts[1]);
                            // Vulnerable: logging raw user input
                            tracing::info!(username = username, "auth attempt");
                        }
                    }
                }
            }
        }
    }
    Ok((http::StatusCode::OK, "Hello"))
}

The vulnerable example logs the raw username, which may contain newlines or structured text. An attacker can craft a header to inject additional log lines or metadata.

// Remediated example: sanitize before logging
use axum::{routing::get, Router, extract::Request};
use std::convert::Infallible;

async fn handler(
    request: Request,
) -> Result {
    if let Some(auth_header) = request.headers().get("authorization") {
        if let Ok(auth_str) = auth_header.to_str() {
            if auth_str.starts_with("Basic ") {
                let encoded = auth_str.strip_prefix("Basic ").unwrap_or("");
                if let Ok(decoded) = base64::decode(encoded) {
                    if let Ok(credentials) = String::from_utf8(decoded) {
                        let parts: Vec<&str> = credentials.splitn(2, ':').collect();
                        if parts.len() == 2 {
                            let (username, _password) = (parts[0], parts[1]);
                            // Remediation: validate and sanitize username
                            let safe_username = if username.chars().all(|c| c.is_alphanumeric() || c == '_' || c == '-') {
                                username.to_string()
                            } else {
                                "unknown".to_string()
                            };
                            // Safe: only sanitized identifier logged
                            tracing::info!(username = safe_username.as_str(), "auth attempt");
                        }
                    }
                }
            }
        }
    }
    Ok((http::StatusCode::OK, "Hello"))
}

In the remediated version, the username is validated against a strict pattern before logging. Newline characters and special symbols are excluded, preventing injection. For production use, consider hashing the username (e.g., with a stable, non-reversible hash) for correlation without exposing raw identifiers. Additionally, structured logging formats can reduce risk by ensuring log lines are parsed as single records. Combine these practices with Axum middleware that enforces authentication uniformly, and avoid logging the password component entirely.

Frequently Asked Questions

Can log injection in Axum with Basic Auth alter application behavior?
Direct behavior alteration is unlikely because logs are typically consumed asynchronously, but injection can corrupt log structure, break parsers, and obscure genuine events, which may indirectly affect incident response.
Does middleBrick detect log injection risks during scans?
middleBrick runs 12 security checks in parallel, including checks relevant to authentication and input validation contexts. While it does not test application logging code directly, findings related to authentication and data exposure can highlight environments where log injection risk is elevated.