CWE-119: Failure to Constrain Operations within the Bounds of a Memory Buffer
Failure to Constrain Operations within the Bounds of a Memory Buffer
Weakness ID: 119 (Weakness Class)
Status: Usable
Description
Description Summary
The software performs operations on a memory buffer, but it can
read from or write to a memory location that is outside of the intended boundary
of the buffer.
Extended Description
Certain languages allow direct addressing of memory locations and do not
automatically ensure that these locations are valid for the memory buffer
that is being referenced. This can cause read or write operations to be
performed on memory locations that may be associated with other variables,
data structures, or internal program data.
As a result, an attacker may be able to execute arbitrary code, alter the
intended control flow, read sensitive information, or cause the system to
crash.
Time of Introduction
Architecture and Design
Implementation
Operation
Applicable Platforms
Languages
C: (Often)
C++: (Often)
All
Platform Notes
It is possible in many programming languages to attempt an operation
outside of the bounds of a memory buffer, but the consequences will vary
widely depending on the language, platform, and chip architecture.
Common Consequences
Scope
Effect
Integrity
If the memory accessible by the attacker can be effectively
controlled, it may be possible to execute arbitrary code, as with a
standard buffer overflow.
If the attacker can overwrite a pointer's worth of memory (usually 32
or 64 bits), he can redirect a function pointer to his own malicious
code. Even when the attacker can only modify a single byte arbitrary
code execution can be possible. Sometimes this is because the same
problem can be exploited repeatedly to the same effect. Other times it
is because the attacker can overwrite security-critical
application-specific data -- such as a flag indicating whether the user
is an administrator.
Availability
Out of bounds memory access will very likely result in the corruption
of relevant memory, and perhaps instructions, possibly leading to a
crash. Other attacks leading to lack of availability are possible,
including putting the program into an infinite loop.
Confidentiality
In the case of an out-of-bounds read, the attacker may have access to
sensitive information. If the sensitive information contains system
details, such as the current buffers position in memory, this knowledge
can be used to craft further attacks, possibly with more severe
consequences.
Likelihood of Exploit
High
Demonstrative Examples
Example 1
This example takes an IP address from a user, verifies that it is
well formed and then looks up the hostname and copies it into a
buffer.
(Bad Code)
C
void host_lookup(char *user_supplied_addr){
struct hostent *hp;
in_addr_t *addr;
char hostname[64];
in_addr_t inet_addr(const char *cp);
/*routine that ensures user_supply_addr is in the right format
for conversion */
validate_addr_form(user_supplied_addr);
addr = inet_addr(user_supplied_addr);
hp = gethostbyaddr( addr, sizeof(struct in_addr),
AF_INET);
strcpy(&hostname, hp->h_name);
}
This function allocates a buffer of 64 bytes to store the hostname,
however there is no guarantee that the hostname will not be larger than
64 bytes. If an attacker specifies an address which resolves to a very
large hostname, then we may overwrite sensitive data or even relinquish
control flow to the attacker.
Example 2
This example applies an encoding procedure to an input string and
stores it into a buffer.
The programmer attempts to encode the ampersand character in the
user-controlled string, however the length of the string is validated
before the encoding procedure is applied. Furthermore, the programmer
assumes encoding expansion will only expand a given character by a
factor of 4, while the encoding of the ampersand expands by 5. As a
result, when the encoding procedure expands the string it is possible to
overflow the destination buffer if the attacker provides a string of
many ampersands.
Example 3
The following example asks a user for an offset into an array to
select an item.
The programmer allows the user to specify which element in the list to
select, however an attacker can provide an out-of-bounds offset,
resulting in a buffer over-read (CWE-126).
OS kernel trusts userland-supplied length value,
allowing reading of sensitive information
Potential Mitigations
Phase
Description
Requirements
Use a language with features that can automatically mitigate or
eliminate buffer overflows.
For example, many languages that perform their own memory management,
such as Java and Perl, are not subject to buffer overflows. Other
languages, such as Ada and C#, typically provide overflow protection,
but the protection can be disabled by the programmer.
Be wary that a language's interface to native code may still be
subject to overflows, even if the language itself is theoretically safe.
Architecture and Design
Use languages, libraries, or frameworks that make it easier to manage
buffers without exceeding their boundaries.
Examples include the Safe C String Library (SafeStr) by Messier and
Viega, and the Strsafe.h library from Microsoft. These libraries provide
safer versions of overflow-prone string-handling functions. This is not
a complete solution, since many buffer overflows are not related to
strings.
Build and Compilation
Run or compile your software using features or extensions that
automatically provide a protection mechanism that mitigates or
eliminates buffer overflows.
For example, certain compilers and extensions provide automatic buffer
overflow detection mechanisms that are built into the compiled code.
Examples include the Microsoft Visual Studio /GS flag, Fedora/Red Hat
FORTIFY_SOURCE GCC flag, StackGuard, and ProPolice.
This is not necessarily a complete solution, since these mechanisms
can only detect certain types of overflows. In addition, a buffer
overflow attack can still cause a denial of service, since the typical
response is to exit the application.
Implementation
Programmers should adhere to the following rules when allocating and
managing their application's memory:
Double check that your buffer is as large as you specify.
When using functions that accept a number of bytes to copy, such
as strncpy(), be aware that if the destination buffer size is equal
to the source buffer size, it may not NULL-terminate the
string.
Check buffer boundaries if calling this function in a loop and
make sure you are not in danger of writing past the allocated
space.
If necessary, truncate all input strings to a reasonable length
before passing them to the copy and concatenation functions.
Testing
Use automated static analysis tools that target this type of weakness.
Many modern techniques use data flow analysis to minimize the number of
false positives. This is not a perfect solution, since 100% accuracy and
coverage are not feasible.
Testing
Use dynamic tools and techniques that interact with the software using
large test suites with many diverse inputs, such as fuzz testing
(fuzzing), robustness testing, and fault injection. The software's
operation may slow down, but it should not become unstable, crash, or
generate incorrect results.
Operation
Use a feature like Address Space Layout Randomization (ASLR). This is
not a complete solution. However, it forces the attacker to guess an
unknown value that changes every program execution.
Operation
Use a CPU and operating system that offers Data Execution Protection
(NX) or its equivalent. This is not a complete solution, since buffer
overflows could be used to overwrite nearby variables to modify the
software's state in dangerous ways. In addition, it cannot be used in
cases in which self-modifying code is required.