CWE 125 - Out-of-Bounds Read
About CWE ID 125
Out-of-Bounds Read
This Vulnerability occurs when a program reads data past the end or before the beginning of a buffer, which can result in reading unintended or sensitive information, or even cause the program to crash.
Impact
Privilege Escalation
Data Corruption or Manipulation
Denial of Service (DoS)
Example with Code Explanation
C
C
Let us consider an example case and understand the CWE 125 with context of Vulnerable code and Mitigated code.
#include <stdio.h>
#include <string.h>
void vulnerable_function(char *input_string) {
char buffer[10];
strcpy(buffer, input_string); // potential out-of-bounds read vulnerability
printf("%s\n", buffer);
}
int main() {
char input[20] = "This is a test";
vulnerable_function(input);
return 0;
}
The
vulnerable_function
function takes a string input and copies it to a buffer with a fixed size of 10 characters using thestrcpy
function. If the input string is longer than 10 characters,strcpy
will write past the end of thebuffer
, leading to an out-of-bounds read vulnerability. Themain
function passes a string input of 20 characters to thevulnerable_function
, which may cause it to read beyond the end of the buffer, potentially leading to unexpected behavior or security issues.Some of the ways the Vulnerable code can be mitigated is:
Ensure that the
input length
ischecked
before copying the input to the buffer to avoid writing beyond the end of the buffer.Use safer string functions such as
strncpy
orsnprintf
that limit the number of characters copied and prevent buffer overflows.Use compiler flags such as
-fstack-protector
to enable stack canaries, which can help detect buffer overflows at runtime.Use a buffer size that is large enough to accommodate the maximum expected input size, or dynamically allocate memory to store the input.
Mitigated Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_INPUT_LENGTH 100
void safer_function(const char *input_string) {
char *buffer = (char *) malloc(MAX_INPUT_LENGTH + 1); // dynamically allocate buffer
if (buffer == NULL) {
printf("Error: Could not allocate memory for buffer.\n");
exit(1);
}
strncpy(buffer, input_string, MAX_INPUT_LENGTH); // use strncpy to limit the number of characters copied
buffer[MAX_INPUT_LENGTH] = '\0'; // add null terminator to the end of the string
printf("%s\n", buffer);
free(buffer); // free dynamically allocated memory
}
int main() {
safer_function("Hello, world!");
return 0;
}
The Mitigated code does the following:
The buffer size is dynamically allocated to a maximum length of
MAX_INPUT_LENGTH
characters, which can accommodate all expected inputs without overflowing the buffer.The
strncpy
function is used to limit the number of characters copied to the buffer, preventing overflows and ensuring that the null terminator is included.A
null terminator
is added to the end of the string to ensure that it is properly terminated, preventing out-of-bounds reads of uninitialized memory.After the use of the buffer, the dynamically allocated memory is freed,
preventing memory leaks
and ensuring that the buffer is not used after it has been freed.
C++
C++
Vulnerable Code
#include <iostream>
#include <cstring>
void vulnerable_function(char *input_string) {
char buffer[10];
std::strcpy(buffer, input_string); // potential out-of-bounds read vulnerability
std::cout << buffer << std::endl;
}
int main() {
char input[20] = "This is a test";
vulnerable_function(input);
return 0;
}
In this vulnerable code, the
vulnerable_function
function takes a string input and copies it to a buffer with a fixed size of 10 characters using thestrcpy
function. If the input string is longer than 10 characters,strcpy
will write past the end of thebuffer
, leading to an out-of-bounds read vulnerability.The
main
function passes a string input of 20 characters to thevulnerable_function
, which may cause it to read beyond the end of the buffer, potentially leading to unexpected behavior or security issues.Some of the ways the Vulnerable code can be mitigated is:
Ensure that the
input length is checked
before copying the input to the buffer to avoid writing beyond the end of the buffer.Use a buffer size that is large enough to accommodate the maximum expected input size, or dynamically allocate memory to store the input.
Use safer string functions such as
strncpy
orsnprintf
that limit the number of characters copied and prevent buffer overflows.Use C++ standard library classes like
std::string
instead of C-style strings and character arrays, which have built-in boundary checking and can help prevent buffer overflows.
Mitigated Code
#include <iostream>
#include <string>
void safe_function(const std::string& input_string) {
const size_t MAX_INPUT_LENGTH = 10;
char buffer[MAX_INPUT_LENGTH + 1] = {0}; // allocate memory for buffer and initialize it to 0
const size_t copy_len = std::min(input_string.length(), MAX_INPUT_LENGTH); // ensure that we don't copy more than MAX_INPUT_LENGTH characters
size_t result = snprintf(buffer, MAX_INPUT_LENGTH + 1, "%s", input_string.substr(0, copy_len).c_str()); // use snprintf to copy input_string into buffer and ensure null termination
if (result > MAX_INPUT_LENGTH) {
std::cerr << "Error: Input string too long!" << std::endl;
return;
}
std::cout << buffer << std::endl;
}
int main() {
std::string input = "This is a test";
safe_function(input);
return 0;
}
The Mitigated code does the following:
The
safe_function()
function usessnprintf()
to copy the input string into the buffer, which ensures that the copied string is null-terminated and will not write beyond the buffer's size.The function checks if the return value of
snprintf()
is greater thanMAX_INPUT_LENGTH
. If it is, then it prints an error message and returns immediately, preventing any further code execution that might use the buffer.
Java
Java
Vulnerable Code
public class OutOfBoundsReadExample {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5};
int index = 5; // This index is out of bounds
int result = numbers[index]; // Accessing an array element out of bounds
System.out.println(result);
}
}
We have an array of integers called
numbers
that has five elements. We then attempt to access an element of the array using an index of5
. Since the array only has five elements, the index of5
is out of bounds, and attempting to access this element will result in an out-of-bounds read.Some of the ways the vulnerability can be remediated is:
Use defensive programming techniques, such as
input validation and error checking
, to catch out-of-bounds read errors before they occur.Always ensure that
array indices
used to access array elements are within the bounds of the array.Use Java's built-in bounds checking mechanism to help prevent out-of-bounds read vulnerabilities.
Mitigated Code
public class MitigatedOutOfBoundsReadExample {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5};
int index = 5;
if (isValidIndex(index, numbers)) { // Check if the index is within bounds
int result = numbers[index];
System.out.println(result);
} else {
System.out.println("Index is out of bounds.");
}
}
public static boolean isValidIndex(int index, int[] array) {
return index >= 0 && index < array.length;
}
}
The Mitigated code does the following:
We've added a method called
isValidIndex()
that checks if the given index is within the bounds of the given array.In the main method, we use this
isValidIndex()
method to check if the index is within bounds before attempting to access the corresponding array element.If the index is
out of bounds
, we print an error message instead of attempting to access the array element.
References
Last updated
Was this helpful?