Out Of Bounds Read in Axum with Mutual Tls
Out Of Bounds Read in Axum with Mutual Tls — how this specific combination creates or exposes the vulnerability
An Out Of Bounds Read occurs when a program reads memory beyond the intended buffer. In Axum, this typically arises from unchecked indexing into arrays, slices, or collections. When Mutual Tls is enforced, the server validates client certificates before processing the request, but if the application logic that handles certificate metadata (e.g., subject fields, serial numbers) or request-derived indices lacks proper bounds checks, the combination can expose sensitive memory or cause undefined behavior.
Consider an Axum handler that uses a client certificate’s serial number to index into a fixed-size lookup table without validating the range. Because Mutual Tls ensures the client presents a certificate, the developer might assume the input is safe. However, serial numbers can be large integers or non-sequential values. Using them directly as an index may read outside the table’s allocated memory. Axum’s extractor patterns, such as State or custom extractors that parse certificates, can inadvertently pass unchecked values into downstream processing if developers do not explicitly validate numeric ranges or collection lengths.
Moreover, request bodies deserialized into structures may include length-prefixed fields. If the length is not validated against the actual buffer size before slicing, an Out Of Bounds Read can occur when accessing the buffer. This risk is not eliminated by Mutual Tls, which only secures transport and identity; it does not enforce correctness of application-level data handling. The scanner’s checks—such as Input Validation and Property Authorization—can surface these flaws by detecting missing bounds checks in endpoints that rely on certificate-derived data.
In practice, an attacker could supply a carefully crafted certificate with an unusual serial number or manipulate request parameters to trigger the out-of-bounds access. The consequence may include information disclosure or process instability, though exploitation depends on memory layout and runtime environment. Because Axum does not inherently prevent such indexing errors, developers must enforce rigorous validation regardless of Mutual Tls presence.
Mutual Tls-Specific Remediation in Axum — concrete code fixes
Remediation focuses on validating all data derived from the client certificate and request payload before using it as an index or buffer offset. Below are concrete Axum examples demonstrating safe patterns.
1. Validating certificate serial numbers before using them as indices:
use axum::{routing::get, Router};
use std::net::SocketAddr;
use axum::extract::State;
use serde::Serialize;
struct AppState {
lookup_table: Vec,
}
async fn handler(
State(state): State<AppState>,
// Assume extract_certificate returns Result<CertificateData, ...>
certificate_data: CertificateData,
) -> String {
let index = certificate_data.serial_number as usize;
// Validate index against the table length
if index < state.lookup_table.len() {
state.lookup_table[index].clone()
} else {
"Invalid index".to_string()
}
}
#[tokio::main]
async fn main() {
let state = AppState {
lookup_table: vec!["safe".to_string(); 10],
};
let app = Router::new()
.route("/data", get(handler))
.with_state(state);
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
2. Bounds-checking length-prefixed buffers extracted from request bodies:
use axum::{routing::post, Json};
use serde::Deserialize;
#[derive(Deserialize)]
struct Payload {
length: usize,
data: Vec<u8>,
}
async fn process_payload(Json(payload): Json<Payload>) -> String {
// Ensure length matches the actual data size
if payload.length != payload.data.len() {
return "Length mismatch".to_string();
}
// Safe access within bounds
for i in 0..payload.length {
// Process payload.data[i] safely
let _ = payload.data[i];
}
"OK".to_string()
}
3. Using iterator methods that inherently enforce bounds, such as get, instead of direct indexing:
let value = state.lookup_table.get(index).cloned().unwrap_or_else(|| "fallback".to_string());
These examples illustrate that Mutual Tls in Axum does not mitigate application-level bounds errors. Remediation requires explicit validation of indices and lengths, regardless of transport security.