HIGH out of bounds readaws

Out Of Bounds Read on Aws

How Out Of Bounds Read Manifests in Aws

An out‑of‑bounds read occurs when a program accesses memory beyond the limits of a buffer, often leaking data that was previously stored in that memory region. In AWS‑based services the issue typically appears when code assumes a fixed size for data returned from an API (e.g., S3 object body, DynamoDB attribute, API Gateway payload) and copies that data into a pre‑allocated buffer without verifying the actual length returned by the SDK.

Consider a Lambda function written in Go that retrieves an object from Amazon S3 and reads its contents into a fixed‑size byte slice. If the object is smaller than the slice, the unused tail of the slice retains whatever data happened to be in memory from previous invocations. Returning that slice (or a string built from it) can expose internal variables, encryption keys, or other sensitive information—a classic information‑leak via out‑of‑bounds read.

package main

import (
	"context"
	"fmt"
	"io"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/s3"
)

func handler(ctx context.Context, bucket, key string) (string, error) {
	cfg, err := config.LoadDefaultConfig(ctx)
	if err != nil {
		return "", err
	}
	client := s3.NewFromConfig(cfg)

	resp, err := client.GetObject(ctx, &s3.GetObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
	})
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	// Vulnerable: fixed 2 KB buffer, but we ignore the actual bytes read
	buf := make([]byte, 2048)
	_, err = io.ReadFull(resp.Body, buf) // ReadFull returns error if less than 2048 bytes
	if err != nil && err != io.EOF {
		return "", err
	}
	// BUG: using the whole buffer leaks leftover memory
	return string(buf), nil
}

Aws-Specific Detection

Detecting an out‑of‑bounds read in a black‑box scenario relies on observing abnormal responses when the service is fed input that deviates from expected sizes. middleBrick performs unauthenticated probing of the API surface and looks for two complementary signals:

  • Length‑based probing: it sends requests with progressively larger values for parameters that control data size (e.g., Content-Length header, query‑string limit, or S3 object key length) and measures whether the response contains extra data beyond what was requested.
  • Content‑analysis: if the response includes repetitive patterns, null bytes, or data that matches previous request payloads, it flags a possible buffer over‑read.

For the S3‑GetObject example above, middleBrick would:

  1. Upload a small object (e.g., 100 bytes) to a public bucket (or rely on an existing public object).
  2. Issue a GET request that asks for the object without any range header.
  3. Inspect the response body; if the byte count exceeds the object’s actual size and the tail contains non‑zero data that does not belong to the object, the finding is reported as an out‑of‑bounds read with severity high.

The scanner also cross‑references any OpenAPI/Swagger specification to verify whether the operation defines a maximum length for payloads; missing or overly permissive definitions increase the confidence of the finding.

CheckWhat middleBrick Looks ForOutcome
Length‑based probingResponses larger than declared sizePotential OOB read
Content tail analysisRepeated or stale data in excess bytesConfirmed information leak
Spec validationMissing maxLength on request/response schemasIncreases finding confidence

Aws-Specific Remediation

The fix is to always respect the actual length returned by the AWS SDK and avoid using a buffer larger than the data that was read. In most languages the SDK already provides the length (or number of bytes read) as part of the result; the developer must slice the buffer accordingly before further processing.

Below is the corrected version of the Go Lambda handler. It uses the number of bytes actually read (n) to create a properly sized slice, eliminating the possibility of leaking stale memory.

package main

import (
	"context"
	"fmt"
	"io"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/service/s3"
)

func handler(ctx context.Context, bucket, key string) (string, error) {
	cfg, err := config.LoadDefaultConfig(ctx)
	if err != nil {
		return "", err
	}
	client := s3.NewFromConfig(cfg)

	resp, err := client.GetObject(ctx, &s3.GetObjectInput{
		Bucket: aws.String(bucket),
		Key:    aws.String(key),
	})
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()

	// First, read into a temporary buffer to discover the actual size
	tmp := make([]byte, 32*1024) // 32 KiB temporary buffer – safe upper bound
	n, err := io.ReadFull(resp.Body, tmp)
	if err != nil && err != io.EOF {
		return "", err
	}
	// Use only the bytes that were actually read
	data := tmp[:n]
	return string(data), nil
}

Alternative approaches that are equally safe:

  • Use io.ReadAll (Go 1.16+) which returns a freshly allocated slice containing exactly the data read:
  • data, err := io.ReadAll(resp.Body)
    

  • In Python with boto3, avoid pre‑allocating a bytearray and instead let Body.read() return a bytes object:
  • import boto3
    s3 = boto3.client('s3')
    resp = s3.get_object(Bucket=bucket, Key=key)
    data = resp['Body'].read()   # returns exact bytes
    

  • For Java, use S3Object.getObjectContent() which returns an S3ObjectInputStream; read into a ByteArrayOutputStream or similar that grows as needed.

By coupling these coding practices with middleBrick’s continuous monitoring (available on the Pro and Enterprise tiers), you can ensure that any future change that re‑introduces a fixed‑buffer assumption is caught before it reaches production.

Frequently Asked Questions

Does middleBrick need credentials or agents to detect an out‑of‑bounds read in my AWS‑hosted API?
No. middleBrick performs unauthenticated, black‑box scanning; you only provide the public URL of the endpoint. It sends crafted requests and analyses the responses without requiring any AWS IAM keys, agents, or network agents.
If middleBrick flags an out‑of‑bounds read, does it automatically patch the vulnerable code?
middleBrick only detects and reports the issue. It supplies detailed findings, severity, and remediation guidance, but it does not modify, block, or fix the code. You must apply the suggested fixes in your own repository.