CWE 787 -Out of Bounds Write
About CWE ID 787
Out of Bounds Write
This Vulnerability occurs when a program writes data outside of the intended buffer or memory location.
Impact
Buffer Overflow
Code/Command Execution
DoS/Data Corruption
Privilege Escalation/Crash
Example with Code Explanation:
C++
C++
Let us consider an example case and understand the CWE 787 with context of Vulnerable code and Mitigated code.
Vulnerable Code
#include <iostream>
#include <cstring>
int main(int argc, char* argv[]) {
char buffer[10];
strcpy(buffer, argv[1]);
std::cout << buffer << std::endl;
return 0;
}
This code is vulnerable to buffer overflow because the
strcpy
function is being used to copy user input fromargv[1]
into the fixed-sizebuffer
array. Also, Thestrcpy
function doesn't check the length of the input being copied, so if the input is longer than 10 characters, it will overwrite adjacent memory, potentially causing a crash or allowing an attacker to execute arbitrary code.Some of the ways the vulnerable code can be mitigated is:
Check the length of the input before copying it, and reject input that is too large.
Use
strlcpy()
instead ofstrcpy()
which is similar tostrncpy()
but ensure NULL termination of the string.Use
strncpy()
instead ofstrcpy()
and pass the size of the buffer as the maximum number of characters to copy.Use a library function specifically designed to safely copy strings, such as
strscpy()
.Use a library that has built-in bounds checking, such as the C++
string
class.
Mitigated Code
#include <iostream>
#include <cstring>
int main(int argc, char* argv[]) {
char buffer[10];
size_t input_length = strlen(argv[1]);
if (input_length >= sizeof(buffer)) {
std::cout << "Input too long!" << std::endl;
return -1;
}
strlcpy(buffer, argv[1], sizeof(buffer));
std::cout << buffer << std::endl;
return 0;
}
The mitigated code does the following:
First, it calculates the length of the input string using
strlen(argv[1])
and stores it in theinput_length
variable.Next, it checks whether the input string is longer than the size of the buffer using an if statement. If it is, the program prints an error message and exits with a non-zero status code. This prevents a buffer overflow from occurring if the input string is too large.
If the input string is shorter than the buffer, it calls
strlcpy
function with three arguments: the destination buffer, the source string, and the size of the buffer. This function copies at mostsize-1
bytes from the source string to the destination buffer, and then it adds a null-terminating byte. It also returns the total length of the string it tried to create, so if the returned value is greater or equal to the size of the buffer that means the buffer is truncated and it will not overflow.Finally, it prints the contents of the buffer using
std::cout << buffer << std::endl;
and the program exits with a zero status code.
💡 Another way is to use **`strncat`** or **`strlcat`** , which will append the input string to the buffer, and ensure that the buffer is null-terminated.
Java
Java
Vulnerable Code
public class OutOfBoundsWrite {
public static void main(String[] args) {
// Allocate an array of 10 integers
int[] array = new int[10];
// Read an index and a value from the command line
int index = Integer.parseInt(args[0]);
int value = Integer.parseInt(args[1]);
// Write the value to the specified index of the array
array[index] = value;
}
}
The code above is vulnerable to CWE-787, due to the lack of
input validation
,bounds checking
andinsufficient input handling
. The program reads index and value from command line, but it doesn't check the index is within the bounds of the array, this can cause anArrayIndexOutOfBoundsException
. Also, the code usesparseInt
method to convert the arguments which doesn't perform any input validation and can throw an exception. In addition, the program doesn't check the number of arguments and doesn't initialize the array with specific values which can lead to sensitive data leakage.Some of the ways the code can be mitigated is:
Perform input validation to ensure that the
index
andvalue
passed as command line arguments are integers and within the expected range.Check that the
index
is within thebounds of the array
before using it to access an element in the array.Sanitize
the inputs. Ensure that the inputs are only coming from a valid source, and in a valid format
Mitigated Code
public class OutOfBoundsWrite {
public static void main(String[] args) {
if(args.length < 2) {
System.out.println("Please provide two arguments, index and value");
return;
}
int[] array = new int[10];
int index;
int value;
try {
index = Integer.parseInt(args[0]);
value = Integer.parseInt(args[1]);
// Check if value is too large for array
if (value >= int.MinValue && value <= int.MaxValue) {
if (index >= 0 && index < array.length) {
array[index] = value;
} else {
System.out.println("Index is out of bounds");
}
} else {
System.out.println("Value is too large for array");
}
} catch (NumberFormatException e) {
System.out.println("Index and value should be integers");
return;
}
}
}
The Mitigated code does the following:
The code takes two arguments from command line, first one is
index
and second one isvalue
. It creates an array of size 10 and then it checks the following points:whether the index is within the bounds of the array
(index >= 0 && index < array.length)
whether the value is within the valid range for int
(value >= int.MinValue && value <= int.MaxValue)
if both of the above conditions are met, it assigns the value to the specified
index
in the array.
The code also checks if the provided arguments are integers, if not, it notifies the user and exits.
This code has following mitigations:
Checking the index is within the bounds of the array
Checking the value is within the valid range for int
Checking if the provided arguments are integers
Checking if the two arguments are provided
.NET
.NET
Vulnerable Code
public class OutOfBoundsWrite
{
public static void Main(string[] args)
{
// Allocate an array of 10 integers
int[] array = new int[10];
// Read an index and a value from the command line
int index = int.Parse(args[0]);
int value = int.Parse(args[1]);
// Write the value to the specified index of the array
array[index] = value;
}
}
The above code is vulnerable due to:
The code does not perform any
input validation
on theindex
andvalue
passed as arguments to the program.The
int.Parse()
method is used to convert the input strings to integers, but it does not check if the input strings are valid integers or if the resulting integers are within the bounds of the array
The Vulnerable code can be mitigated by:
Add
validation check
to ensure that the provided index is within the bounds of the array before using it to access the array.Add check to ensure that the provided value is within the
valid range
before using it to write to the array.add check for number of
input
variableuse
try catch block
for number format exception for index and valuereturn error message if any of the above case not met
Mitigated Code
using System;
class OutOfBoundsWrite {
static void Main(string[] args) {
if(args.Length < 2) {
Console.WriteLine("Please provide two arguments, index and value");
return;
}
int[] array = new int[10];
int index;
int value;
try {
index = int.Parse(args[0]);
value = int.Parse(args[1]);
// Check if index is within the array bounds
if (index >= 0 && index < array.Length) {
// Check if value is within the valid range for int
if (value >= int.MinValue && value <= int.MaxValue) {
array[index] = value;
} else {
Console.WriteLine("Value is out of range");
}
} else {
Console.WriteLine("Index is out of bounds");
}
} catch (FormatException e) {
Console.WriteLine("Index and value should be integers");
return;
}
}
}
The Mitigated Code does the following:
It checks if the number of arguments passed is less than 2 and returns an error message if that is the case.
It checks if the provided index is within the bounds of the array before using it.
It checks if the provided value is within the valid range for int before using it.
It uses the
try-catch
block to handle the exception if the arguments passed are not integers.
References
Last updated
Was this helpful?