The accidental addition of a data-structure sentinel can cause
serious programming logic problems.
Extended Description
Data-structure sentinels are often used to mark the structure of data. A
common example of this is the null character at the end of strings or a
special sentinel to mark the end of a linked list. It is dangerous to allow
this type of control data to be easily accessible. Therefore, it is
important to protect from the addition or modification of sentinels.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C
C++
Common Consequences
Scope
Effect
Availability
Generally this error will cause the data structure to not work
properly by truncating the data.
Likelihood of Exploit
High to Very High
Demonstrative Examples
Example 1
The following example assigns some character values to a list of
characters and prints them each individually, and then as a string. The
third character value is intended to be an integer taken from user input and
converted to an int.
The first print statement will print each character separated by a
space. However, if a non-integer is read from stdin by getc, then atoi
will not make a conversion and return 0. When foo is printed as a
string, the 0 at character foo[2] will act as a NULL terminator and
foo[3] will never be printed.
Potential Mitigations
Phase
Description
Implementation
Architecture and Design
Encapsulate the user from interacting with data sentinels. Validate
user input to verify that sentinels are not present.
Implementation
Proper error checking can reduce the risk of inadvertently introducing
sentinel values into data. For example, if a parsing function fails or
encounters an error, it might return a value that is the same as the
sentinel.
Requirements
Use a language or compiler that performs automatic bounds
checking.
Architecture and Design
Use an abstraction library to abstract away risky APIs. This is not a
complete solution.
Build and Compilation
Compiler-based canary mechanisms such as StackGuard, ProPolice, and
Microsoft Visual Studio /GS flag. Unless this provides automatic bounds
checking, it is not a complete solution.
Operation
Use OS-level preventative functionality. This is not a complete
solution.
The code uses an operator for assignment when the intention was
to perform a comparison.
Extended Description
In many languages the compare statement is very close in appearance to the
assignment statement and are often confused. This bug is generally the
result of a typo and usually causes obvious problems with program execution.
If the comparison is in an if statement, the if statement will usually
evaluate the value of the right-hand side of the predicate.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Java
.NET
Likelihood of Exploit
Low
Demonstrative Examples
Example 1
The following C/C++ and C# examples attempt to validate an int input
parameter against the integer value 100. However, the expression to be
evaluated in the if statement uses the assignment operator "=" rather than
the comparison operator "==". The result of using the assignment operator
instead of the comparison operator causes the int variable to be reassigned
locally and the expression in the if statement will always evaluate to the
value on the right hand side of the expression. This will result in the
input value not being properly validated, which can cause unexpected
results.
(Bad Code)
C and C#
int isValid(int value) {
if (value=100) {
printf("Value is valid\n");
return(1);
}
printf("Value is not valid\n");
return(0);
}
(Bad Code)
C#
bool isValid(int value) {
if (value=100) {
Console.WriteLine("Value is valid.");
return true;
}
Console.WriteLine("Value is not valid.");
return false;
}
Example 2
In this example, we show how assigning instead of comparing can
impact code when values are being passed by reference instead of by value.
Consider a scenario in which a string is being processed from user input.
Assume the string has already been formatted such that different user inputs
are concatenated with the colon character. When the processString function
is called, the test for the colon character will result in an insertion of
the colon character instead, adding new input separators. Since the string
was passed by reference, the data sentinels will be inserted in the original
string (CWE-464), and further processing of the inputs will be altered,
possibly malformed..
(Bad Code)
C
void processString (char *str) {
int i;
for(i=0; i<strlen(str); i++) {
if (isalnum(str[i])){
processChar(str[i]);
}
else if (str[i] = ':') {
movingToNewInput();}
}
}
}
Example 3
The following Java example attempts to perform some processing based
on the boolean value of the input parameter. However, the expression to be
evaluated in the if statement uses the assignment operator "=" rather than
the comparison operator "==". As with the previous examples, the variable
will be reassigned locally and the expression in the if statement will
evaluate to true and unintended processing may occur.
(Bad Code)
Java
public void checkValid(boolean isValid) {
if (isValid = true) {
System.out.println("Performing processing");
doSomethingImportant();
}
else {
System.out.println("Not Valid, do not perform
processing");
return;
}
}
While most Java compilers will catch the use of an assignment operator
when a comparison operator is required, for boolean variables in Java
the use of the assignment operator within an expression is allowed. If
possible, try to avoid using comparison operators on boolean variables
in java. Instead, let the values of the variables stand for themselves,
as in the following code.
(Good Code)
Java
public void checkValid(boolean isValid) {
if (isValid) {
System.out.println("Performing processing");
doSomethingImportant();
}
else {
System.out.println("Not Valid, do not perform
processing");
return;
}
}
Alternatively, to test for false, just use the boolean NOT
operator.
(Good Code)
Java
public void checkValid(boolean isValid) {
if (!isValid) {
System.out.println("Not Valid, do not perform
processing");
return;
}
System.out.println("Performing processing");
doSomethingImportant();
}
Example 4
(Bad Code)
C
void called(int foo){
if (foo=1) printf("foo\n");
}
int main() {
called(2);
return 0;
}
Potential Mitigations
Phase
Description
Pre-design: Through Build: Many IDEs and static analysis products will
detect this problem.
Implementation
Place constants on the left. If one attempts to assign a constant with
a variable, the compiler will of course produce an error.
Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
Definition in a New Window
Compound Element ID: 120 (Compound Element Base: Composite)
Status: Incomplete
Description
Description Summary
The program copies an input buffer to an output buffer without
verifying that the size of the input buffer is less than the size of the output
buffer, leading to a buffer overflow.
Extended Description
A buffer overflow condition exists when a program attempts to put more
data in a buffer than it can hold, or when a program attempts to put data in
a memory area outside of the boundaries of a buffer. The simplest type of
error, and the most common cause of buffer overflows, is the "classic" case
in which the program copies the buffer without checking its length at all.
Other variants exist, but the existence of a classic overflow strongly
suggests that the programmer is not considering even the most basic of
security protections.
Alternate Terms
buffer overrun:
Some prominent vendors and researchers use the term "buffer overrun,"
but most people use "buffer overflow."
Unbounded Transfer
Terminology Notes
Many issues that are now called "buffer overflows" are substantively
different than the "classic" overflow, including entirely different bug
types that rely on overflow exploit techniques, such as integer signedness
errors, integer overflows, and format string bugs. This imprecise
terminology can make it difficult to determine which variant is being
reported.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C
C++
Common Consequences
Scope
Effect
Availability
Buffer overflows generally lead to crashes. Other attacks leading to
lack of availability are possible, including putting the program into an
infinite loop.
Integrity
Buffer overflows often can be used to execute arbitrary code, which is
usually outside the scope of a program's implicit security
policy.
Integrity
When the consequence is arbitrary code execution, this can often be
used to subvert any other security service.
By replacing a valid cookie value with an
extremely long string of characters, an attacker may overflow the
application's buffers.
Potential Mitigations
Phase
Description
Architecture and Design
Use an abstraction library to abstract away risky APIs. Examples
include the Safe C String Library (SafeStr) by Viega, and the Strsafe.h
library from Microsoft. This is not a complete solution, since many
buffer overflows are not related to strings.
Architecture and Design
Use the <strsafe.h> library. This library has buffer
overflow safe functions that will help with the detection of buffer
overflows.
Build and Compilation
Use automatic buffer overflow detection mechanisms that are offered by
certain compilers or compiler extensions. Examples include StackGuard,
ProPolice and the Microsoft Visual Studio /GS flag. This is not
necessarily a complete solution, since these canary-based mechanisms
only detect certain types of overflows. In addition, the result is still
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 applications 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.
Truncate all input strings to a reasonable length before passing them to
the copy and concatenation functions
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.
Build and Compilation
Operation
Most mitigating technologies at the compiler or OS level to date
address only a subset of buffer overflow problems and rarely provide
complete protection against even that subset. It is good practice to
implement strategies to increase the workload of an attacker, such as
leaving the attacker to guess an unknown value that changes every
program execution.
Weakness Ordinalities
Ordinality
Description
Resultant
(where the
weakness is typically related to the presence of some other
weaknesses)
Primary
(where the
weakness exists independent of other weaknesses)
At the code level, stack-based and heap-based overflows do not differ
significantly, so there usually is not a need to distinguish them. From the
attacker perspective, they can be quite different, since different
techniques are required to exploit them.
Affected Resources
Memory
Functional Areas
Memory Management
Causal Nature
Explicit
Taxonomy Mappings
Mapped Taxonomy Name
Node ID
Fit
Mapped Node Name
PLOVER
Unbounded Transfer ('classic overflow')
7 Pernicious Kingdoms
Buffer Overflow
CLASP
Buffer overflow
OWASP Top Ten 2004
A1
CWE More Specific
Unvalidated Input
OWASP Top Ten 2004
A5
CWE More Specific
Buffer Overflows
CERT C Secure Coding
STR35-C
Do not copy data from an unbounded source to a fixed-length
array
A weakness where the code path includes a Buffer Write Operation such
that:
1. the expected size of the buffer is greater than the actual size of
the buffer where expected size is equal to the sum of the size of the
data item and the position in the buffer
Where Buffer Write Operation is a statement that writes a data item of a
certain size into a buffer at a certain position and at a certain
index
The software reads from a buffer using buffer access
mechanisms such as indexes or pointers that reference memory locations after the
targeted buffer.
Extended Description
This typically occurs when the pointer or its index is incremented to a
position beyond the bounds of the buffer or when pointer arithmetic results
in a position outside of the valid memory location to name a few. This may
result in exposure of sensitive information or possibly a crash.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Weakness Ordinalities
Ordinality
Description
Primary
(where the
weakness exists independent of other weaknesses)
The software reads from a buffer using buffer access
mechanisms such as indexes or pointers that reference memory locations prior to
the targeted buffer.
Extended Description
This typically occurs when the pointer or its index is decremented to a
position before the buffer, when pointer arithmetic results in a position
before the beginning of the valid memory location, or when a negative index
is used. This may result in exposure of sensitive information or possibly a
crash.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Weakness Ordinalities
Ordinality
Description
Primary
(where the
weakness exists independent of other weaknesses)
The software writes to a buffer using an index or pointer that
references a memory location prior to the beginning of the buffer.
Extended Description
This typically occurs when a pointer or its index is decremented to a
position before the buffer, when pointer arithmetic results in a position
before the beginning of the valid memory location, or when a negative index
is used.
Alternate Terms
buffer underrun:
Some prominent vendors and researchers use the term "buffer underrun".
"Buffer underflow" is more commonly used, although both terms are also
sometimes used to describe a buffer under-read (CWE-127).
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C
C++
Common Consequences
Scope
Effect
Availability
Out of bounds memory access will very likely result in the corruption
of relevant memory, and perhaps instructions, possibly leading to a
crash.
Access Control
If the corrupted memory can be effectively controlled, it may be
possible to execute arbitrary code. If the corrupted memory is data
rather than instructions, the system will continue to function with
improper changes, possibly in violation of an implicit or explicit
policy. The consequences would only be limited by how the affected data
is used, such as an adjacent memory location that is used to specify
whether the user has special privileges.
Other
When the consequence is arbitrary code execution, this can often be
used to subvert any other security service.
Likelihood of Exploit
Medium
Demonstrative Examples
Example 1
The following is an example of code that may result in a buffer
underwrite, if find() returns a negative value to indicate that ch is not
found in srcBuf:
Buffer underflow from an all-whitespace string,
which causes a counter to be decremented before the buffer while looking for
a non-whitespace character.
This could be resultant from several errors, including a bad offset or an
array index that decrements before the beginning of the buffer (see
CWE-129).
Research Gaps
Much attention has been paid to buffer overflows, but "underflows"
sometimes exist in products that are relatively free of overflows, so it is
likely that this variant has been under-studied.
Causal Nature
Explicit
Taxonomy Mappings
Mapped Taxonomy Name
Node ID
Fit
Mapped Node Name
PLOVER
UNDER - Boundary beginning violation ('buffer
underflow'?)
Compiler Optimization Removal or Modification of Security-critical Code
Definition in a New Window
Weakness ID: 733 (Weakness Base)
Status: Incomplete
Description
Description Summary
The developer builds a security-critical protection mechanism
into the software but the compiler optimizes the program such that the mechanism
is removed or modified.
Applicable Platforms
Languages
C: (Often)
C++: (Often)
All Compiled Languages
Detection Factors
Black Box:
This specific weakness is impossible to detect using black box
methods. While an analyst could examine memory to see that it has not
been scrubbed, an analysis of the executable would not be successful.
This is because the compiler has already removed the relevant code. Only
the source code shows whether the programmer intended to clear the
memory or not, so this weakness is indistinguishable from others.
White Box:
This weakness is only detectable using white box methods (see black
box detection factor). Careful analysis is required to determine if the
code is likely to be removed by the compiler.
Sensitive memory is cleared according to the source code, but
compiler optimizations leave the memory untouched when it is not read from
again, aka "dead store removal."
Extended Description
This compiler optimization error occurs when:
1. Secret data are stored in memory.
2. The secret data are scrubbed from memory by overwriting its
contents.
3. The source code is compiled using an optimizing compiler, which
identifies and removes the function that overwrites the contents as a
dead store because the memory is not used subsequently.
Time of Introduction
Implementation
Build and Compilation
Applicable Platforms
Languages
C
C++
Detection Factors
Black Box:
This specific weakness is impossible to detect using black box
methods. While an analyst could examine memory to see that it has not
been scrubbed, an analysis of the executable would not be successful.
This is because the compiler has already removed the relevant code. Only
the source code shows whether the programmer intended to clear the
memory or not, so this weakness is indistinguishable from others.
White Box:
This weakness is only detectable using white box methods (see black
box detection factor). Careful analysis is required to determine if the
code is likely to be removed by the compiler.
Demonstrative Examples
Example 1
The following code reads a password from the user, uses the password
to connect to a back-end mainframe and then attempts to scrub the password
from memory using memset().
(Bad Code)
C
void GetData(char *MFAddr) {
char pwd[64];
if (GetPasswordFromUser(pwd, sizeof(pwd))) {
if (ConnectToMainframe(MFAddr, pwd)) {
// Interaction with mainframe
}
}
memset(pwd, 0, sizeof(pwd));
}
The code in the example will behave correctly if it is executed
verbatim, but if the code is compiled using an optimizing compiler, such
as Microsoft Visual C++ .NET or GCC 3.x, then the call to memset() will
be removed as a dead store because the buffer pwd is not used after its
value is overwritten [18]. Because the buffer pwd contains a sensitive
value, the application may be vulnerable to attack if the data are left
memory resident. If attackers are able to access the correct region of
memory, they may use the recovered password to gain control of the
system. It is common practice to overwrite sensitive data manipulated in
memory, such as passwords or cryptographic keys, in order to prevent
attackers from learning system secrets. However, with the advent of
optimizing compilers, programs do not always behave as their source code
alone would suggest. In the example, the compiler interprets the call to
memset() as dead code because the memory being written to is not
subsequently used, despite the fact that there is clearly a security
motivation for the operation to occur. The problem here is that many
compilers, and in fact many programming languages, do not take this and
other security concerns into consideration in their efforts to improve
efficiency. Attackers typically exploit this type of vulnerability by
using a core dump or runtime mechanism to access the memory used by a
particular application and recover the secret information. Once an
attacker has access to the secret information, it is relatively
straightforward to further exploit the system and possibly compromise
other resources with which the application interacts.
Potential Mitigations
Phase
Description
Implementation
Store the sensitive data in a "volatile" memory location if
available.
Build and Compilation
If possible, configure your compiler so that it does not remove dead
stores.
Architecture and Design
Where possible, encrypt sensitive data that are used by a software
system.
The accidental deletion of a data-structure sentinel can cause
serious programming logic problems.
Extended Description
Often times data-structure sentinels are used to mark structure of the
data structure. A common example of this is the null character at the end of
strings. Another common example is linked lists which may contain a sentinel
to mark the end of the list. It is dangerous to allow this type of control
data to be easily accessible. Therefore, it is important to protect from the
deletion or modification outside of some wrapper interface which provides
safety.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C
C++
Common Consequences
Scope
Effect
Availability
Generally this error will cause the data structure to not work
properly.
Authorization
If a control character, such as NULL is removed, one may cause
resource access control problems.
Demonstrative Examples
Example 1
C and C++
char *foo;
int counter;
foo=malloc(sizeof(char)*10);
for (counter=0;counter!=14;counter++) {
foo[counter]='a';
printf("%s\n",foo);
}
Potential Mitigations
Phase
Description
Requirements
Use a language or compiler that performs automatic bounds
checking.
Architecture and Design
Use an abstraction library to abstract away risky APIs. Not a complete
solution.
Build and Compilation
Compiler-based canary mechanisms such as StackGuard, ProPolice and the
Microsoft Visual Studio /GS flag. Unless this provides automatic bounds
checking, it is not a complete solution.
Operation
Use OS-level preventative functionality. Not a complete
solution.
The product calls free() twice on the same memory address,
potentially leading to modification of unexpected memory
locations.
Extended Description
When a program calls free() twice with the same argument, the program's
memory management data structures become corrupted. This corruption can
cause the program to crash or, in some circumstances, cause two later calls
to malloc() to return the same pointer. If malloc() returns the same value
twice and the program later gives the attacker control over the data that is
written into this doubly-allocated memory, the program becomes vulnerable to
a buffer overflow attack.
Alternate Terms
Double-free
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C
C++
Common Consequences
Scope
Effect
Access Control
Doubly freeing memory may result in a write-what-where condition,
allowing an attacker to execute arbitrary code.
Likelihood of Exploit
Low to Medium
Demonstrative Examples
Example 1
The following code shows a simple example of a double free
vulnerability.
(Bad Code)
C
char* ptr = (char*)malloc (SIZE);
...
if (abrt) {
free(ptr);
}
...
free(ptr);
Double free vulnerabilities have two common (and sometimes
overlapping) causes:
Error conditions and other exceptional circumstances
Confusion over which part of the program is responsible for
freeing the memory
Although some double free vulnerabilities are not much more
complicated than the previous example, most are spread out across
hundreds of lines of code or even different files. Programmers seem
particularly susceptible to freeing global variables more than
once.
Example 2
While contrived, this code should be exploitable on Linux
distributions which do not ship with heap-chunk check summing turned
on.
Choose a language that provides automatic memory management.
Implementation
Ensure that each allocation is freed only once. After freeing a chunk,
set the pointer to NULL to ensure the pointer cannot be freed again. In
complicated error conditions, be sure that clean-up routines respect the
state of allocation properly. If the language is object oriented, ensure
that object destructors delete each chunk of memory only once.
Implementation
Use a static analysis tool to find double free instances.
This is usually resultant from another weakness, such as an unhandled
error or race condition between threads. It could also be primary to
weaknesses such as buffer overflows.
Affected Resources
Memory
Taxonomy Mappings
Mapped Taxonomy Name
Node ID
Fit
Mapped Node Name
PLOVER
DFREE - Double-Free Vulnerability
7 Pernicious Kingdoms
Double Free
CLASP
Doubly freeing memory
CERT C Secure Coding
MEM00-C
Allocate and free memory in the same module, at the same level
of abstraction
CERT C Secure Coding
MEM01-C
Store a new value in pointers immediately after
free()
CERT C Secure Coding
MEM31-C
Free dynamically allocated memory exactly
once
White Box Definitions
A weakness where code path has:
1. start statement that relinquishes a dynamically allocated memory
resource
2. end statement that relinquishes the dynamically allocated memory
resource
Maintenance Notes
It could be argued that Double Free would be most appropriately located as
a child of "Use after Free", but "Use" and "Release" are considered to be
distinct operations within vulnerability theory, therefore this is more
accurately "Release of a Resource after Expiration or Release", which
doesn't exist yet.
Content History
Submissions
Submission Date
Submitter
Organization
Source
PLOVER
Externally Mined
Modifications
Modification Date
Modifier
Organization
Source
2008-07-01
Eric Dalci
Cigital
External
updated Potential Mitigations,
Time of Introduction
2008-08-01
KDM Analytics
External
added/updated white box definitions
2008-09-08
CWE Content Team
MITRE
Internal
updated Applicable Platforms, Common Consequences,
Description, Maintenance Notes, Relationships, Other Notes,
Relationship Notes, Taxonomy Mappings
Duplicate keys in associative lists can lead to non-unique keys
being mistaken for an error.
Extended Description
A duplicate key entry -- if the alist is designed properly -- could be
used as a constant time replace function. However, duplicate key entries
could be inserted by mistake. Because of this ambiguity, duplicate key
entries in an association list are not recommended and should not be
allowed.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C
C++
Java
.NET
Likelihood of Exploit
Low
Demonstrative Examples
Example 1
The following code adds data to a list and then attempts to sort the
data.
(Bad Code)
alist = []
while (foo()): #now assume there is a string data with a key
basename
queue.append(basename,data)
queue.sort()
Since basename is not necessarily unique, this may not sort how one
would like it to be.
Potential Mitigations
Phase
Description
Architecture and Design
Use a hash table instead of an alist.
Architecture and Design
Use an alist which checks the uniqueness of hash keys with each entry
before inserting the entry.
The software implements an IOCTL with functionality that should
be restricted, but it does not properly enforce access control for the
IOCTL.
Extended Description
When an IOCTL contains privileged functionality and is exposed
unnecessarily, attackers may be able to access this functionality by
invoking the IOCTL. Even if the functionality is benign, if the programmer
has assumed that the IOCTL would only be accessed by a trusted process,
there may be little or no validation of the incoming data, exposing
weaknesses that would never be reachable if the attacker cannot call the
IOCTL directly.
The implementations of IOCTLs will differ between operating system types
and versions, so the methods of attack and prevention may vary
widely.
Applicable Platforms
Languages
C: (Often)
C++: (Often)
Operating Systems
UNIX-based
Windows-based
Platform Notes
Because IOCTL functionality is typically performing low-level actions and
closely interacts with the operating system, this weakness may only appear
in code that is written in low-level languages.
Common Consequences
Scope
Effect
Integrity
Availability
Confidentiality
Attackers can invoke any functionality that the IOCTL offers.
Depending on the functionality, the consequences may include code
execution, denial-of-service, and theft of data.
This can be primary to many other weaknesses when the programmer assumes
that the IOCTL can only be accessed by trusted parties. For example, a
program or driver might not validate incoming addresses in METHOD_NEITHER
IOCTLs in Windows environments (CWE-781), which could allow buffer overflow
and similar attacks to take place, even when the attacker never should have
been able to access the IOCTL at all.
Failure to Change Working Directory in chroot Jail
Definition in a New Window
Weakness ID: 243 (Weakness Variant)
Status: Draft
Description
Description Summary
The program uses the chroot() system call to create a jail, but
does not change the working directory afterward. This does not prevent access to
files outside of the jail.
Extended Description
Improper use of chroot() may allow attackers to escape from the chroot
jail. The chroot() function call does not change the process's current
working directory, so relative paths may still refer to file system
resources outside of the chroot jail after chroot() has been called.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Operating Systems
UNIX
Likelihood of Exploit
High
Demonstrative Examples
Example 1
Consider the following source code from a (hypothetical) FTP
server:
(Bad Code)
C
chroot("/var/ftproot");
...
fgets(filename, sizeof(filename), network);
localfile = fopen(filename, "r");
while ((len = fread(buf, 1, sizeof(buf), localfile)) != EOF)
{
fwrite(buf, 1, sizeof(buf), network);
}
fclose(localfile);
This code is responsible for reading a filename from the network,
opening the corresponding file on the local machine, and sending the
contents over the network. This code could be used to implement the FTP
GET command. The FTP server calls chroot() in its initialization
routines in an attempt to prevent access to files outside of
/var/ftproot. But because the server fails to change the current working
directory by calling chdir("/"), an attacker could request the file
"../../../../../etc/passwd" and obtain a copy of the system password
file.
Background Details
The chroot() system call allows a process to change its perception of the
root directory of the file system. After properly invoking chroot(), a
process cannot access any files outside the directory tree defined by the
new root directory. Such an environment is called a chroot jail and is
commonly used to prevent the possibility that a processes could be subverted
and used to access unauthorized files. For instance, many FTP servers run in
chroot jails to prevent an attacker who discovers a new vulnerability in the
server from being able to download the password file or other sensitive
files on the system.
Weakness Ordinalities
Ordinality
Description
Resultant
(where the
weakness is typically related to the presence of some other
weaknesses)
Failure to Clear Heap Memory Before Release ('Heap Inspection')
Definition in a New Window
Weakness ID: 244 (Weakness Variant)
Status: Draft
Description
Description Summary
Using realloc() to resize buffers that store sensitive
information can leave the sensitive information exposed to attack, because it is
not removed from memory.
Extended Description
When sensitive data such as a password or an encryption key is not removed
from memory, it could be exposed to an attacker using a "heap inspection"
attack that reads the sensitive data using memory dumps or other methods.
The realloc() function is commonly used to increase the size of a block of
allocated memory. This operation often requires copying the contents of the
old memory block into a new and larger block. This operation leaves the
contents of the original block intact but inaccessible to the program,
preventing the program from being able to scrub sensitive data from memory.
If an attacker can later examine the contents of a memory dump, the
sensitive data could be exposed.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Common Consequences
Scope
Effect
Confidentiality
Be careful using vfork() and fork() in security sensitive code. The
process state will not be cleaned up and will contain traces of data
from past use.
Demonstrative Examples
Example 1
The following code calls realloc() on a buffer containing sensitive
data:
There is an attempt to scrub the sensitive data from memory, but
realloc() is used, so a copy of the data can still be exposed in the
memory originally allocated for cleartext_buffer.
Failure to Constrain Operations within the Bounds of a Memory Buffer
Definition in a New Window
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.
Failure to Release Memory Before Removing Last Reference ('Memory Leak')
Definition in a New Window
Weakness ID: 401 (Weakness Base)
Status: Draft
Description
Description Summary
The software does not sufficiently track and release allocated
memory after it has been used, which slowly consumes remaining
memory.
Extended Description
This is often triggered by improper handling of malformed data or
unexpectedly interrupted sessions.
Terminology Notes
"memory leak" has sometimes been used to describe other kinds of issues,
e.g. for information leaks in which the contents of memory are inadvertently
leaked (CVE-2003-0400 is one such example of this terminology
conflict).
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C
C++
Modes of Introduction
Memory leaks have two common and sometimes overlapping causes:
Error conditions and other exceptional circumstances
Confusion over which part of the program is responsible for freeing
the memory
Common Consequences
Scope
Effect
Availability
Most memory leaks result in general software reliability problems, but
if an attacker can intentionally trigger a memory leak, the attacker
might be able to launch a denial of service attack (by crashing or
hanging the program) or take advantage of other unexpected program
behavior resulting from a low memory condition.
Likelihood of Exploit
Medium
Demonstrative Examples
Example 1
The following C function leaks a block of allocated memory if the
call to read() fails to return the expected number of bytes:
(Bad Code)
C
char* getBlock(int fd) {
char* buf = (char*) malloc(BLOCK_SIZE);
if (!buf) {
return NULL;
}
if (read(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) {
return NULL;
}
return buf;
}
Example 2
Here the problem is that every time a connection is made, more
memory is allocated. So if one just opened up more and more connections,
eventually the machine would run out of memory.
Pre-design: Use a language or compiler that performs automatic bounds
checking.
Architecture and Design
Use an abstraction library to abstract away risky APIs. Not a complete
solution.
Pre-design through Build: The Boehm-Demers-Weiser Garbage Collector or
valgrind can be used to detect leaks in code. This is not a complete
solution as it is not 100% effective.
This is often a resultant weakness due to improper handling of malformed
data or early termination of sessions.
Affected Resources
Memory
Functional Areas
Memory management
Taxonomy Mappings
Mapped Taxonomy Name
Node ID
Fit
Mapped Node Name
PLOVER
Memory leak
7 Pernicious Kingdoms
Memory Leak
CLASP
Failure to deallocate data
OWASP Top Ten 2004
A9
CWE More Specific
Denial of Service
White Box Definitions
A weakness where the code path has:
1. start statement that allocates dynamically allocated memory
resource
2. end statement that loses identity of the dynamically allocated
memory resource creating situation where dynamically allocated memory
resource is never relinquished
Where "loses" is defined through the following scenarios:
1. identity of the dynamic allocated memory resource never
obtained
2. the statement assigns another value to the data element that stored
the identity of the dynamically allocated memory resource and there are
no aliases of that data element
3. identity of the dynamic allocated memory resource obtained but
never passed on to function for memory resource release
4. the data element that stored the identity of the dynamically
allocated resource has reached the end of its scope at the statement and
there are no aliases of that data element
References
J. Whittaker and
H. Thompson. "How to Break Software Security". Addison Wesley. 2003.
Content History
Submissions
Submission Date
Submitter
Organization
Source
PLOVER
Externally Mined
Modifications
Modification Date
Modifier
Organization
Source
2008-07-01
Eric Dalci
Cigital
External
updated Time of Introduction
2008-08-01
KDM Analytics
External
added/updated white box definitions
2008-08-15
Veracode
External
Suggested OWASP Top Ten 2004
mapping
2008-09-08
CWE Content Team
MITRE
Internal
updated Applicable Platforms, Common Consequences,
Relationships, Other Notes, References, Relationship Notes,
Taxonomy Mappings, Terminology Notes
The software calls a function, procedure, or routine, but the
caller specifies too many arguments, or too few arguments, which may lead to
undefined behavior and resultant weaknesses.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
Perl
Modes of Introduction
This problem typically occurs when the programmer makes a typo, or copy
and paste errors.
Detection Factors
While this weakness might be caught by the compiler in some languages,
it can occur more frequently in cases in which the called function
accepts variable numbers of arguments, such as format strings in C. It
also can occur in languages or environments that do not require that
functions always be called with the correct number of arguments, such as
Perl.
Potential Mitigations
Phase
Description
Use the function, procedure, routine as specified.
Because this function call often produces incorrect behavior it will
usually be detected during testing or normal operation of the software.
During testing exercise all possible control paths will typically expose
this weakness except in rare cases when the incorrect function call
accidentally produces the correct results or if the provided argument
type is very similar to the expected argument type.
Weakness Ordinalities
Ordinality
Description
Primary
(where the
weakness exists independent of other weaknesses)
Function Call With Incorrect Variable or Reference as Argument
Definition in a New Window
Weakness ID: 688 (Weakness Variant)
Status: Draft
Description
Description Summary
The software calls a function, procedure, or routine, but the
caller specifies the wrong variable or reference as one of the arguments, which
may lead to undefined behavior and resultant weaknesses.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
Perl
Modes of Introduction
This problem typically occurs when the programmer makes a typo, or copy
and paste errors.
Detection Factors
While this weakness might be caught by the compiler in some languages,
it can occur more frequently in cases in which the called function
accepts variable numbers of arguments, such as format strings in C. It
also can occur in loosely typed languages or environments. This might
require an understanding of intended program behavior or design to
determine whether the value is incorrect.
Demonstrative Examples
Example 1
In the following Java snippet, the accessGranted() method is
accidentally called with the static ADMIN_ROLES array rather than the user
roles.
(Bad Code)
Java
private static final String[] ADMIN_ROLES = ...;
public boolean void accessGranted(String resource, String user)
{
Kernel code specifies the wrong variable in first
argument, leading to resultant NULL pointer
dereference.
Potential Mitigations
Phase
Description
Use the function, procedure, routine as specified.
Because this function call often produces incorrect behavior it will
usually be detected during testing or normal operation of the software.
During testing exercise all possible control paths will typically expose
this weakness except in rare cases when the incorrect function call
accidentally produces the correct results or if the provided argument
type is very similar to the expected argument type.
Weakness Ordinalities
Ordinality
Description
Primary
(where the
weakness exists independent of other weaknesses)
A heap overflow condition is a buffer overflow, where the
buffer that can be overwritten is allocated in the heap portion of memory,
generally meaning that the buffer was allocated using a routine such as
malloc().
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C
C++
Common Consequences
Scope
Effect
Availability
Buffer overflows generally lead to crashes. Other attacks leading to
lack of availability are possible, including putting the program into an
infinite loop.
Access Control
Buffer overflows often can be used to execute arbitrary code, which is
usually outside the scope of a program's implicit security
policy.
Besides important user data, heap-based overflows can be used to
overwrite function pointers that may be living in memory, pointing it to
the attacker's code. Even in applications that do not explicitly use
function pointers, the run-time will usually leave many in memory. For
example, object methods in C++ are generally implemented using function
pointers. Even in C programs, there is often a global offset table used
by the underlying runtime.
Other
When the consequence is arbitrary code execution, this can often be
used to subvert any other security service.
Chain: integer signedness passes signed
comparison, leads to heap overflow
Potential Mitigations
Phase
Description
Pre-design: Use a language or compiler that performs automatic bounds
checking.
Architecture and Design
Use an abstraction library to abstract away risky APIs. Not a complete
solution.
Pre-design through Build: Canary style bounds checking, library
changes which ensure the validity of chunk data, and other such fixes
are possible, but should not be relied upon.
Implement and perform bounds checking on input.
Do not use dangerous functions such as gets. Look for their safe
equivalent, which checks for the boundary.
Operational: Use OS-level preventative functionality. This is not a
complete solution, but it provides some defense in depth.
Weakness Ordinalities
Ordinality
Description
Primary
(where the
weakness exists independent of other weaknesses)
Improper Address Validation in IOCTL with METHOD NEITHER I/O Control Code
Definition in a New Window
Weakness ID: 781 (Weakness Variant)
Status: Draft
Description
Description Summary
The software defines an IOCTL that uses METHOD_NEITHER for I/O,
but it does not validate or incorrectly validates the addresses that are
provided.
Extended Description
When an IOCTL uses the METHOD_NEITHER option for I/O control, it is the
responsibility of the IOCTL to validate the addresses that have been
supplied to it. If validation is missing or incorrect, attackers can supply
arbitrary memory addresses, leading to code execution or a denial of
service.
Applicable Platforms
Languages
C: (Often)
C++: (Often)
Operating Systems
Windows XP: (Sometimes)
Windows 2000: (Sometimes)
Windows Vista: (Sometimes)
Platform Notes
Because IOCTL functionality is typically performing low-level actions and
closely interacts with the operating system, this weakness may only appear
in code that is written in low-level languages.
Common Consequences
Scope
Effect
Integrity
Availability
Attackers can write to an attacker-controlled memory address. If the
attacker can control the contents that the IOCTL writes, it may lead to
code execution at high privilege levels. At the least, a crash can
occur.
chain: device driver for packet-capturing software
allows access to an unintended IOCTL with resultant array index
error.
Potential Mitigations
Phase
Description
Implementation
If METHOD_NEITHER is required for the IOCTL, then ensure that you
validate all user-space addresses properly before they are first
accessed. The ProbeForRead and ProbeForWrite routines are available for
this task. Also properly protect and manage the user-supplied buffers,
since the I/O Manager does not do this when METHOD_NEITHER is being
used. See References.
Architecture and Design
If possible, avoid using METHOD_NEITHER in the IOCTL and select
methods that effectively control the buffer size, such as
METHOD_BUFFERED, METHOD_IN_DIRECT, or METHOD_OUT_DIRECT.
Architecture and Design
Implementation
If the IOCTL is part of a driver that is only intended to be accessed
by trusted users, then use proper access control for the associated
device or device namespace. See References.
While this type of issue has been known since 2006, it is probably still
under-studied and under-reported. Most of the focus has been on high-profile
software and security products, but other kinds of system software also use
drivers. Since exploitation requires the development of custom code, it
requires some skill to find this weakness.
Because exploitation typically requires local privileges, it might not be
a priority for active attackers. However, remote exploitation may be
possible for software such as device drivers. Even when remote vectors are
not available, it may be useful as the final privilege-escalation step in
multi-stage remote attacks against application-layer software, or as the
primary attack by a local user on a multi-user system.
The product does not clean up its state or incorrectly cleans
up its state when an exception is thrown, leading to unexpected state or control
flow.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Java
.NET
Common Consequences
Scope
Effect
Integrity
The code could be left in a bad state.
Likelihood of Exploit
Medium
Demonstrative Examples
Example 1
(Bad Code)
C++ and Java
public class foo {
public static final void main( String args[] ) {
boolean returnValue;
returnValue=doStuff();
}
public static final boolean doStuff( ) {
boolean threadLock;
boolean truthvalue=true;
try {
while(
//check some condition
) {
threadLock=true; //do some stuff to
truthvalue
threadLock=false;
}
}
catch (Exception e){
System.err.println("You did something bad");
if (something) return truthvalue;
}
return truthvalue;
}
}
In this case, you may leave a thread locked accidentally.
Potential Mitigations
Phase
Description
Implementation
If one breaks from a loop or function by throwing an exception, make
sure that cleanup happens or that you should exit the program. Use
throwing exceptions sparsely.
Other Notes
Often, when functions or loops become complicated, some level of cleanup
in the beginning to the end is needed. Often, since exceptions can disturb
the flow of the code, one can leave a code block in a bad state.
Improper Handling of Length Parameter Inconsistency
Definition in a New Window
Weakness ID: 130 (Weakness Base)
Status: Incomplete
Description
Description Summary
The software does not handle or incorrectly handles incoming
data that contains a length or size field that is inconsistent with the actual
length of the associated data.
Extended Description
If an attacker can manipulate the length parameter associated with an
input such that it is inconsistent with the actual length of the input, this
can be leveraged to cause the target application to behave in unexpected,
and possibly, malicious ways. One of the possible motives for doing so is to
pass in arbitrarily large input to the application. Another possible
motivation is the modification of application state by including invalid
data for subsequent properties of the application. Such weaknesses commonly
lead to attacks such as buffer overflows and execution of arbitrary
code.
The software does not terminate or incorrectly terminates a
string or array with a null character or equivalent
terminator.
Extended Description
Null termination errors frequently occur in two different ways. An
off-by-one error could cause a null to be written out of bounds, leading to
an overflow. Or, a program could use a strncpy() function call incorrectly,
which prevents a null terminator from being added at all. Other scenarios
are possible.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Platform Notes
Conceptually, this does not just apply to the C language; any language or
representation that involves a terminator could have this type of
problem.
Common Consequences
Scope
Effect
Confidentiality
Integrity
The case of an omitted null character is the most dangerous of the
possible issues. This will almost certainly result in information
disclosure, and possibly a buffer overflow condition, which may be
exploited to execute arbitrary code.
Confidentiality
Integrity
Availability
If a null character is omitted from a string, then most string-copying
functions will read data until they locate a null character, even
outside of the intended boundaries of the string. This could:
cause a crash due to a segmentation fault
cause sensitive adjacent memory to be copied and sent to an
outsider
trigger a buffer overflow when the copy is bering written to a
fixed-size buffer
Integrity
Availability
Misplaced null characters may result in any number of security
problems. The biggest issue is a subset of buffer overflow, and
write-what-where conditions, where data corruption occurs from the
writing of a null character over valid data, or even instructions. A
randomly placed null character may put the system into an undefined
state, and therefore make it prone to crashing. A misplaced null
character may corrupt other data in memory
Access Control
Should the null character corrupt the process flow, or affect a flag
controlling access, it may lead to logical errors which allow for the
execution of arbitrary code.
Likelihood of Exploit
Medium
Demonstrative Examples
Example 1
The following code reads from cfgfile and copies the input into
inputbuf using strcpy(). The code mistakenly assumes that inputbuf will
always contain a NULL terminator.
(Bad Code)
C
#define MAXLEN 1024
...
char *pathbuf[MAXLEN];
...
read(cfgfile,inputbuf,MAXLEN); //does not null terminate
The code above will behave correctly if the data read from cfgfile is
null terminated on disk as expected. But if an attacker is able to
modify this input so that it does not contain the expected NULL
character, the call to strcpy() will continue copying from memory until
it encounters an arbitrary NULL character. This will likely overflow the
destination buffer and, if the attacker can control the contents of
memory immediately following inputbuf, can leave the application
susceptible to a buffer overflow attack.
Example 2
In the following code, readlink() expands the name of a symbolic
link stored in the buffer path so that the buffer filename contains the
absolute path of the file referenced by the symbolic link. The length of the
resulting value is then calculated using strlen().
(Bad Code)
C
char buf[MAXPATH];
...
readlink(path, buf, MAXPATH);
int length = strlen(filename);
...
The code above will not behave correctly because the value read into
buf by readlink() will not be null terminated. In testing,
vulnerabilities like this one might not be caught because the unused
contents of buf and the memory immediately following it may be NULL,
thereby causing strlen() to appear as if it is behaving correctly.
However, in the wild strlen() will continue traversing memory until it
encounters an arbitrary NULL character on the stack, which results in a
value of length that is much larger than the size of buf and may cause a
buffer overflow in subsequent uses of this value. Buffer overflows
aside, whenever a single call to readlink() returns the same value that
has been passed to its third argument, it is impossible to know whether
the name is precisely that many bytes long, or whether readlink() has
truncated the name to avoid overrunning the buffer. Traditionally,
strings are represented as a region of memory containing data terminated
with a NULL character. Older string-handling methods frequently rely on
this NULL character to determine the length of the string. If a buffer
that does not contain a NULL terminator is passed to one of these
functions, the function will read past the end of the buffer. Malicious
users typically exploit this type of vulnerability by injecting data
with unexpected size or content into the application. They may provide
the malicious input either directly as input to the program or
indirectly by modifying application resources, such as configuration
files. In the event that an attacker causes the application to read
beyond the bounds of a buffer, the attacker may be able use a resulting
buffer overflow to inject and execute arbitrary code on the system.
Example 3
While the following example is not exploitable, it provides a good
example of how nulls can be omitted or misplaced, even when "safe" functions
are used:
(Bad Code)
C
#include <stdio.h>
#include <string.h>
int main() {
char longString[] = "String signifying nothing";
char shortString[16];
strncpy(shortString, longString, 16);
printf("The last character in shortString is: %c %1$x\n",
shortString[15]);
return (0);
}
The above code gives the following output: The last character in
shortString is: l 6c So, the shortString array does not end in a NULL
character, even though the "safe" string function strncpy() was
used.
Product does not null terminate a message buffer
after snprintf-like call, leading to
overflow.
Potential Mitigations
Phase
Description
Requirements
Use a language that is not susceptible to these issues. However, be
careful of null byte interaction errors (CWE-626) with lower-level
constructs that may be written in a language that is
susceptible..
Implementation
Ensure that all string functions used are understood fully as to how
they append null characters. Also, be wary of off-by-one errors when
appending nulls to the end of strings.
Implementation
If performance constraints permit, special code can be added that
validates null-termination of string buffers, this is a rather naive and
error-prone solution.
Implementation
Switch to bounded string manipulation functions. Inspect buffer
lengths involved in the buffer overrun trace reported with the
defect.
Implementation
Add code that fills buffers with nulls (however, the length of buffers
still needs to be inspected, to ensure that the non null-terminated
string is not written at the physical end of the buffer).
Weakness Ordinalities
Ordinality
Description
Resultant
(where the
weakness is typically related to the presence of some other
weaknesses)
Factors: this is usually resultant from other weaknesses such as
off-by-one errors, but it can be primary to boundary condition violations
such as buffer overflows. In buffer overflows, it can act as an expander for
assumed-immutable data.
Overlaps missing input terminator.
Causal Nature
Explicit
Taxonomy Mappings
Mapped Taxonomy Name
Node ID
Fit
Mapped Node Name
PLOVER
Improper Null Termination
7 Pernicious Kingdoms
String Termination Error
CLASP
Miscalculated null termination
OWASP Top Ten 2004
A9
CWE More Specific
Denial of Service
CERT C Secure Coding
POS30-C
Use the readlink() function properly
CERT C Secure Coding
STR03-C
Do not inadvertently truncate a null-terminated byte
string
CERT C Secure Coding
STR32-C
Null-terminate byte strings as required
White Box Definitions
A weakness where the code path has:
1. end statement that passes a data item to a null-terminated string
function
2. start statement that produces the improper null-terminated data
item
Where "produces" is defined through the following scenarios:
1. data item never ended with null-terminator
2. null-terminator is re-written
Maintenance Notes
As currently described, this entry is more like a category than a
weakness.
Content History
Submissions
Submission Date
Submitter
Organization
Source
PLOVER
Externally Mined
Modifications
Modification Date
Modifier
Organization
Source
2008-07-01
Eric Dalci
Cigital
External
updated Time of Introduction
2008-08-01
KDM Analytics
External
added/updated white box definitions
2008-09-08
CWE Content Team
MITRE
Internal
updated Applicable Platforms, Causal Nature,
Common Consequences, Description, Likelihood of Exploit, Maintenance Notes,
Relationships, Other Notes, Relationship Notes, Taxonomy Mappings,
Weakness Ordinalities
2008-11-24
CWE Content Team
MITRE
Internal
updated Relationships,
Taxonomy Mappings
2009-03-10
CWE Content Team
MITRE
Internal
updated Common Consequences
2009-05-27
CWE Content Team
MITRE
Internal
updated Demonstrative Examples
2009-07-17
KDM Analytics
External
Improved the White Box Definition
2009-07-27
CWE Content Team
MITRE
Internal
updated Common Consequences, Other Notes,
Potential Mitigations, White Box Definitions
The product uses untrusted input when calculating or using an
array index, but the product does not validate or incorrectly validates the
index to ensure the index references a valid position within the array.
Alternate Terms
out-of-bounds array index
index-out-of-range
array index underflow
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Common Consequences
Scope
Effect
Availability
Unchecked array indexing will very likely result in the corruption of
relevant memory and perhaps instructions, leading to a crash, if the
values are outside of the valid memory area
Integrity
If the memory corrupted is data, rather than instructions, the system
will continue to function with improper values.
Access Control
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.
Likelihood of Exploit
Medium
Demonstrative Examples
Example 1
In the code snippet below, an unchecked integer value is used to
reference an object in an array.
product does not properly track a count and a
maximum number, which can lead to resultant array index
overflow.
Potential Mitigations
Phase
Description
Requirements specification: The choice could be made to use a language
that is not susceptible to these issues.
Implementation
Include sanity checks to ensure the validity of any values used as
index variables. In loops, use greater-than-or-equal-to, or
less-than-or-equal-to, as opposed to simply greater-than, or less-than
compare statements.
Other Notes
A single fault could allow both an overflow and underflow of the array
index.
An index overflow exploit might use buffer overflow techniques, but this
can often be exploited without having to provide "large inputs."
Array index overflows can also trigger out-of-bounds read operations, or
operations on the wrong objects; i.e., "buffer overflows" are not always the
result.
Unchecked array indexing, depending on its instantiation, can be
responsible for any number of related issues. Most prominent of these
possible flaws is the buffer overflow condition. Due to this fact,
consequences range from denial of service, and data corruption, to full
blown arbitrary code execution. The most common condition situation leading
to unchecked array indexing is the use of loop index variables as buffer
indexes. If the end condition for the loop is subject to a flaw, the index
can grow or shrink unbounded, therefore causing a buffer overflow or
underflow. Another common situation leading to this condition is the use of
a function's return value, or the resulting value of a calculation directly
as an index in to a buffer.
Weakness Ordinalities
Ordinality
Description
Resultant
(where the
weakness is typically related to the presence of some other
weaknesses)
Compound Element ID: 692 (Compound Element Base: Chain)
Status: Draft
Description
Description Summary
The product uses a blacklist-based protection mechanism to
defend against XSS attacks, but the blacklist is incomplete, allowing XSS
variants to succeed.