HIGH out of bounds writeactix

Out Of Bounds Write in Actix

How Out Of Bounds Write Manifests in Actix

Out Of Bounds Write vulnerabilities in Actix applications typically occur when handling HTTP request data without proper bounds checking. In Actix, these vulnerabilities often manifest through improper handling of JSON payloads, form data, or path parameters that can lead to memory corruption or data exposure.

A common scenario involves extracting values from JSON bodies without validating their size or structure. For example, an Actix handler might directly deserialize a JSON array into a fixed-size Rust array without checking the input length:

async fn process_data(mut payload: web::Json<Vec<i32>>) -> impl Responder {
    let data = &*payload;
    let fixed_array: [i32; 10] = data.try_into().unwrap_or_default();
    // ... processing logic
}

This code appears safe but can panic or cause undefined behavior if the input array has more than 10 elements. The try_into() call will panic on size mismatch, potentially crashing the service.

Another Actix-specific manifestation occurs with query parameters and path extraction. Consider this route handler:

async fn get_item(
    web::Path((id, index)): web::Path<(i32, usize)>,
    data: web::Data<AppState>
) -> impl Responder {
    let items = &data.items[id as usize];
    let item = items[index];
    HttpResponse::Ok().json(item)
}

If id or index exceed the bounds of the underlying data structures, this can lead to out-of-bounds reads or writes, potentially exposing sensitive data or causing panics.

Actix's extractor system can also introduce vulnerabilities when handling multipart form data. An attacker might craft a multipart request with excessive field counts or oversized content, overwhelming server resources or causing buffer overflows in custom processing logic.

Actix-Specific Detection

Detecting Out Of Bounds Write vulnerabilities in Actix applications requires both static analysis and runtime testing. Static analysis tools can examine the codebase for patterns like unchecked array indexing, unsafe Rust code, and improper use of get_unchecked() or similar methods.

For runtime detection, middleBrick's black-box scanning approach is particularly effective for Actix applications. The scanner tests unauthenticated endpoints by sending crafted payloads designed to trigger out-of-bounds conditions. For JSON endpoints, middleBrick sends arrays of varying sizes, including empty arrays, single-element arrays, and arrays with hundreds of elements to test for proper bounds checking.

The scanner also tests path parameter handling by sending extremely large numeric values, negative numbers, and non-numeric strings where numeric parameters are expected. For example, testing /api/items/9999999999999 when the application only has 100 items can reveal whether proper bounds checking exists.

middleBrick's LLM/AI security module adds another layer of detection for Actix applications that use AI features. It tests for system prompt leakage and prompt injection vulnerabilities that could be exploited to cause out-of-bounds writes in AI-powered Actix endpoints.

Key detection patterns include:

  • Sending JSON arrays larger than expected sizes to test for proper validation
  • Testing path parameters with extreme values to check array indexing safety
  • Submitting multipart forms with excessive field counts
  • Testing for proper error handling when invalid data is provided
  • Checking for information disclosure through error messages that reveal array sizes or internal structure

The Actix framework itself provides some built-in protections, but custom business logic often introduces vulnerabilities. middleBrick's scanning identifies these custom vulnerabilities by testing the actual runtime behavior rather than just the code structure.

Actix-Specific Remediation

Remediating Out Of Bounds Write vulnerabilities in Actix requires a combination of proper input validation, safe Rust practices, and leveraging Actix's built-in safety features. The most effective approach is to validate all input data before processing and use Rust's type system to enforce safety at compile time.

For JSON payload handling, always validate the input size before processing:

async fn process_data(
    payload: web::Json<Vec<i32>>
) -> Result<impl Responder, HttpResponse> {
    let data = &*payload;
    
    if data.len() > 100 {
        return Err(HttpResponse::BadRequest().body("Payload too large"));
    }
    
    let fixed_array: [i32; 100] = data.try_into()
        .map_err(|_| HttpResponse::BadRequest().body("Invalid payload size"))?;
    
    // Safe processing
    Ok(HttpResponse::Ok().json(fixed_array))
}

This approach validates the input length before attempting to convert it to a fixed-size array, returning a proper error response instead of panicking.

For path parameter extraction, use comprehensive validation:

async fn get_item(
    web::Path((id, index)): web::Path<(i32, usize)>,
    data: web::Data<AppState>
) -> Result<impl Responder, HttpResponse> {
    let id = id as usize;
    
    // Validate bounds before accessing
    if id >= data.items.len() {
        return Err(HttpResponse::NotFound().body("Item not found"));
    }
    
    let items = &data.items[id];
    if index >= items.len() {
        return Err(HttpResponse::BadRequest().body("Invalid index"));
    }
    
    Ok(HttpResponse::Ok().json(items[index]))
}

This pattern ensures that all array accesses are validated before use, preventing out-of-bounds access.

Actix's extractor system can be extended with custom validation logic:

use actix_web::{FromRequest, HttpRequest, HttpResponse};

pub struct ValidatedArray(Vec<i32>);

impl<'de> Deserialize<'de> for ValidatedArray {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let vec = Vec::deserialize(deserializer)?;
        if vec.len() > 100 {
            return Err(serde::de::Error::custom("Array too large"));
        }
        Ok(ValidatedArray(vec))
    }
}

impl FromRequest for ValidatedArray {
    type Config = ();
    type Error = actix_web::Error;
    type Future = Ready<Result<Self, Self::Error>>;

    fn from_request(req: &HttpRequest, payload: &mut actix_web::dev::Payload) -> Self::Future {
        web::Json::>::from_request(req, payload)
            .map(|res| {
                let vec = res.map(|v| ValidatedArray(v)).unwrap_or_default();
                Ok(vec)
            })
            .into_future()
    }
}

This custom extractor validates array size during deserialization, providing a reusable validation component.

For comprehensive protection, combine these techniques with Actix's built-in validation features and Rust's ownership system to ensure memory safety throughout your application.

Frequently Asked Questions

How does middleBrick detect Out Of Bounds Write vulnerabilities in Actix applications?
middleBrick uses black-box scanning to test Actix endpoints by sending crafted payloads designed to trigger out-of-bounds conditions. It sends JSON arrays of varying sizes, tests path parameters with extreme values, and submits multipart forms with excessive field counts. The scanner checks for proper error handling and information disclosure through error messages, identifying vulnerabilities without requiring access to source code.
Can Out Of Bounds Write vulnerabilities in Actix lead to data breaches?
Yes, Out Of Bounds Write vulnerabilities can lead to data breaches by allowing attackers to access memory locations outside the intended bounds. This can expose sensitive data stored in adjacent memory, cause application crashes that reveal internal state, or in severe cases, allow arbitrary memory modification. In Actix applications, this often manifests as unauthorized access to array elements or exposure of internal application data through improper bounds checking.