MEDIUM out of bounds readaxum

Out Of Bounds Read in Axum

How Out Of Bounds Read Manifests in Axum

Out Of Bounds Read vulnerabilities in Axum applications typically arise from improper handling of request parameters and body parsing. When Axum extracts data from HTTP requests, developers must ensure bounds checking is performed before accessing arrays, vectors, or string slices.

A common manifestation occurs in path parameter extraction. Consider an endpoint that accepts an array index:

use axum::extract::Path;

#[derive(serde::Deserialize)]
struct Params { 
    index: usize,
    items: Vec<String>,
}

async fn get_item(Params { index, items }: Path<Params>) -> String {
    // Vulnerable: no bounds check
    items[index].clone()
}

If a client requests /items/999 with only 10 items, this triggers an OOB read, potentially exposing memory contents or causing a crash. Axum's extractors don't automatically validate array bounds.

JSON body parsing presents another vector. When deserializing into structs with Vec fields, Axum relies on serde. An attacker can craft oversized arrays or exploit integer parsing:

use axum::extract::Json;
use serde::Deserialize;

#[derive(Deserialize)]
struct Request { 
    data: Vec<u8>,
}

async fn process_data(Json(req): Json<Request>) -> String {
    // Vulnerable if req.data is empty or index is invalid
    format!("{:02x}", req.data[0])
}

The vulnerability here is that serde will happily deserialize any array size, but the handler assumes valid indices exist. This becomes critical when the data influences control flow or is used in subsequent operations.

Axum-Specific Detection

Detecting Out Of Bounds Read vulnerabilities in Axum requires both static analysis and runtime scanning. Static analysis tools can identify patterns where array access lacks bounds checking, but runtime scanning reveals actual exploitable conditions.

middleBrick's black-box scanning approach is particularly effective for Axum applications. The scanner sends crafted requests to test array boundaries:

# Scan an Axum API endpoint
middlebrick scan https://api.example.com/items

The scanner tests for:

  • Path parameters with extreme values (negative numbers, values exceeding typical array sizes)
  • JSON arrays with boundary indices (0, max-1, max, max+1)
  • Header values that might be parsed into numeric indices
  • Query parameters that control array access

For OpenAPI-aware scanning, middleBrick resolves $ref definitions and tests parameter constraints defined in your Axum application's spec. If your Axum app serves OpenAPI documentation, the scanner cross-references runtime behavior with documented schemas.

Manual detection involves testing endpoints with boundary values. For an endpoint expecting an array index, systematically test:

curl https://api.example.com/items/0
curl https://api.example.com/items/1
curl https://api.example.com/items/999999

Watch for differences in response time, error messages, or unexpected data exposure. Axum's default error handling may reveal stack traces or internal state when bounds checks fail.

Axum-Specific Remediation

Remediation in Axum centers on explicit bounds checking before array access. The framework provides several patterns for safe data handling:

use axum::extract::Path;
use axum::http::StatusCode;
use axum::response::IntoResponse;

async fn get_item(Path((index, items)): Path<(usize, Vec<String>)>) -> impl IntoResponse {
    if index >= items.len() {
        return (StatusCode::BAD_REQUEST, "Index out of bounds").into_response();
    }
    
    items[index].clone()
}

For JSON bodies, validate before processing:

use axum::extract::Json;
use axum::http::StatusCode;
use serde::Deserialize;

#[derive(Deserialize)]
struct Request { 
    data: Vec<u8>,
}

async fn process_data(Json(req): Json<Request>) -> impl IntoResponse {
    if req.data.is_empty() {
        return (StatusCode::BAD_REQUEST, "Data array cannot be empty").into_response();
    }
    
    format!("{:02x}", req.data[0])
}

Axum's extract::Query and extract::Path extractors can be wrapped with validation:

use axum::extract::{Path, Query};
use serde::Deserialize;

#[derive(Deserialize)]
struct Params { 
    index: usize,
}

async fn get_item_with_query(
    Path(id): Path<String>,
    Query(params): Query<Params>,
    items: Vec<String>,
) -> impl IntoResponse {
    if params.index >= items.len() {
        return (StatusCode::BAD_REQUEST, "Invalid index").into_response();
    }
    
    items[params.index].clone()
}

For complex validation, create custom extractors that encapsulate bounds checking logic, ensuring consistent security across your Axum application.

Frequently Asked Questions

How does middleBrick detect Out Of Bounds Read vulnerabilities in Axum applications?
middleBrick performs black-box scanning by sending boundary-value requests to your Axum endpoints. It tests path parameters, query parameters, and JSON arrays with extreme values to identify OOB read conditions. The scanner analyzes response patterns, error messages, and timing differences that indicate vulnerable array access. For OpenAPI-aware scanning, it cross-references runtime behavior with your API spec's documented constraints.
Can Axum's extractors prevent Out Of Bounds Read vulnerabilities automatically?
No, Axum's built-in extractors don't perform bounds checking on array access. They extract and parse request data, but leave validation to the handler implementation. You must explicitly check array lengths before accessing elements, whether the data comes from path parameters, query strings, headers, or JSON bodies. This is a common security pitfall in Axum applications.