Formula Injection in Axum with Basic Auth
Formula Injection in Axum with Basic Auth — how this specific combination creates or exposes the vulnerability
Formula Injection occurs when untrusted input is evaluated as a formula or expression by downstream systems such as spreadsheets, reporting tools, or internal data parsers. In Axum, a Rust web framework, this typically arises when user-controlled data captured from HTTP requests—such as query parameters, headers, or body fields—is forwarded to external processing components without validation or sanitization.
When Basic Authentication is used in Axum, the Authorization header is often parsed to extract credentials. If the username or password (or derived values such as tenant identifiers) is later embedded into dynamic content—such as CSV exports, generated reports, or configuration snippets—and that content is consumed by a formula-aware application, attackers can inject malicious payloads. For example, an attacker might supply a username like =">=1+1 or a password containing spreadsheet-style expressions such as =cmd|' /C calc'!A0. If these values are written into a downloaded CSV and opened in Excel, the injected formula executes with the victim’s privileges.
The risk is compounded when Axum services act as intermediaries that transform and relay data. An endpoint that accepts a user identifier and returns a downloadable summary might place the identifier into a generated filename or worksheet cell. Without strict input validation and output encoding, the boundary between data and executable content blurs. This creates a path for unauthorized code execution, data exfiltration, or manipulation of downstream systems, even though the initial API interaction appears limited to authentication and data retrieval.
In the context of middleBrick scanning, endpoints using Basic Auth in Axum are flagged when user-supplied credentials or derived fields appear in responses that could be interpreted as formulas by external applications. The scanner tests whether inputs such as username or password are reflected in downloadable resources or structured outputs, and whether encoding or escaping is consistently applied. Detecting these patterns helps prevent scenarios where an authenticated request leads to unintended execution in client-side tools.
Basic Auth-Specific Remediation in Axum — concrete code fixes
Remediation focuses on ensuring that any data derived from Basic Auth credentials is never directly interpolated into contexts where it can be interpreted as executable formulas. This includes CSV files, URLs, configuration blocks, or any output consumed by spreadsheet or document processors.
1. Avoid embedding credentials in downstream outputs
Do not write usernames or passwords (or hashes derived from them) into files or responses that may be opened in formula-capable applications. If tenant or user identifiers are required, generate independent, non-derived tokens.
2. Validate and sanitize inputs
Reject or normalize inputs that contain formula-like syntax. For identifiers intended for export, strip leading equals signs and disallow characters that trigger formula evaluation in common applications.
3. Encode outputs based on the target format
When generating CSV or similar formats, apply format-specific escaping. For CSV, prefix cells that begin with =, +, -, or @ with a single quote ' to force literal interpretation.
4. Example: Safe Basic Auth parsing and CSV generation in Axum
use axum::{routing::get, Router, http::HeaderMap};
use tower_http::auth::{AuthLayer, credentials::BasicCredentials};
async fn export_user_data(
auth: Option,
headers: HeaderMap,
) -> String {
// Extract and validate credentials
let creds = match auth {
Some(c) => c,
None => return String::from("Unauthorized"),
};
let username = creds.user_id;
// Sanitize: prevent formula injection in CSV
let safe_username = if username.starts_with('=') || username.contains('=') {
// Replace or reject dangerous input
username.replace('=', "_")
} else {
username
};
// Generate CSV with proper escaping
format!("Username,LoginCount\\n'{},5", safe_username)
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/export", get(export_user_data))
.layer(AuthLayer::basic(|_username, _password| async { Ok(()) }));
// Server setup omitted for brevity
}
5. Example: Rejecting suspicious usernames during authentication
use axum::async_trait;
use tower_http::auth::{AuthLayer, credentials::BasicCredentials, ValidateRequest};
struct MyValidator;
#[async_trait]
impl ValidateRequest<BasicCredentials> for MyValidator {
type Rejection = axum::http::StatusCode;
async fn validate(
&self,
creds: BasicCredentials,
) -> Result<(), Self::Rejection> {
// Reject usernames that look like formulas
if creds.user_id.starts_with('=') || creds.user_id.contains('=') {
return Err(axum::http::StatusCode::BAD_REQUEST);
}
// Reject known dangerous patterns
let dangerous_patterns = ["cmd", "/C", "calc"];
if dangerous_patterns.iter().any(|p| creds.user_id.contains(p)) {
return Err(axum::http::StatusCode::BAD_REQUEST);
}
Ok(())
}
}
// Usage:
// let app = Router::new()
// .route("/secure", get(|| async { "ok" }))
// .layer(AuthLayer::basic_with_rejection(MyValidator));
6. Use middleware to sanitize headers before processing
In cases where headers are used for dynamic content generation, sanitize sensitive headers early in the request lifecycle to prevent accidental leakage into downstream contexts.
Frequently Asked Questions
How does middleBrick detect Formula Injection risks in Axum endpoints using Basic Auth?
=1+1 or =cmd|' /C calc'!A0 to be executed as formulas in external applications.