VIEW SLICE: CWE-659: Weaknesses found in the C++ Language
(Draft 9)
View ID
| Status: Draft 659 (View) | | Objective | This view (slice) covers issues that are found in C++ that are not common to all languages. | | View Data | Filter Used: .//Applicable_Platforms/Platform='C++' | CWEs in this view | | Total CWEs |
|---|
| Total | 61 | out of | 695 | | Views | 0 | out of | 14 | | Categories | 2 | out of | 64 | | Weaknesses | 56 | out of | 605 | | Compound_Elements | 3 | out of | 12 |
|
View Components View Components A |
B |
C |
D |
E |
F |
G |
H |
I |
J |
K |
L |
M |
N |
O |
P |
Q |
R |
S |
T |
U |
V |
W |
X |
Y |
Z
Weakness ID
| Status: Incomplete 464 (Weakness Base) | | Description | Summary The accidental addition of a data-structure sentinel can cause serious programming logic
problems. | | Likelihood of Exploit | High to Very High | | Common Consequences | Availability: Generally this error will cause the data structure to not work
properly by truncating the data. | | Potential Mitigations | Pre-design: Use a language or compiler that performs automatic bounds checking. Design: Use an abstraction library to abstract away risky APIs. Not a complete
solution. Pre-design through Build: 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. Operational: Use OS-level preventative functionality. Not a complete
solution. | Demonstrative Examples | C/C++ Example: char *foo; foo=malloc(sizeof(char)*4); foo[0]='a'; foo[1]='a'; foo[2]=0; foo[3]='c'; printf("%c %c %c %c %c \n",foo[0],foo[1],foo[2],foo[3]); printf("%s\n",foo); | | Context Notes | Data-structure sentinels are often 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, of course dangerous,
to allow this type of control data to be easily accessible. Therefore, it is important to protect
from the addition or modification outside of some wrapper interface which provides safety. By
adding a sentinel, one potentially could cause data to be truncated early. | | Relationships | | | Source Taxonomies | CLASP - Addition of data-structure sentinel | | Applicable Platforms | C C++ |
Weakness ID
| Status: Draft 481 (Weakness Variant) | | Description | Summary 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.
| | Likelihood of Exploit | Low | | Potential Mitigations | 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. | Demonstrative Examples | void called(int foo){ if (foo=1) printf("foo\n"); } int main() { called(2); return 0; } | | Context Notes | This bug is generally as a result of a typo and usually should cause obvious
problems with program execution. If the comparison is in an if statement, the if
statement will always return the value of the right-hand side variable. | | Relationships | | | Source Taxonomies | CLASP - Assigning instead of comparing | | Applicable Platforms | C C++ Java .NET |
Weakness ID
| Status: Draft 587 (Weakness Base) | | Description | Summary The software sets a pointer to a specific address other than NULL or 0. Extended Description If the pointer is set to a specific address, that address will probably not be valid in all environments or platforms. | | Weakness Ordinality | Primary (Weakness exists independent of other weaknesses) | | Potential Mitigations | Implementation: Never set a pointer to a fixed address. | Demonstrative Examples | C Example: int (*pt2Function) (float, char, char)=0x08040000; int result2 = (*pt2Function) (12, 'a', 'b'); // Here we can inject code to execute. | | Context Notes | Consequence: Integrity: If one executes code at a known location, one might be able to
inject code there beforehand. Consequence: Confidentiality: The data at a known pointer location can be easily read. Most often, this issue will only result in a crash, but in circumstances where a user
can influence the data at which the pointer points to, it may result in code execution. At best,
using fixed addresses is not portable. | | Relationships | | | Applicable Platforms | C C++ C# Assembly |
Weakness ID
| Status: Incomplete 124 (Weakness Base) | | Description | Summary The software allows a condition where buffers are written to using buffer access mechanisms such as indexes or pointers that reference memory locations prior to the targeted buffer. This typically occurs when indexes are negative numbers or when pointer arithmetic results in a position before the beginning of the valid memory location. This can occur when a negative number is used as an offset, or if the pointer or its index is decremented to a position before the buffer. | | Alternate Terms | 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). | | Likelihood of Exploit | Medium | | Weakness Ordinality | Primary (Weakness exists independent of other weaknesses) | | Causal Nature | Explicit (This is an explicit weakness resulting from behavior of the developer) | | Common Consequences | Availability: Buffer underwrites will very likely result in the corruption of
relevant memory, and perhaps instructions, leading to a crash. Access Control (memory and instruction processing): 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. | | Potential Mitigations | Requirements specification: The choice could be made to use a language that is not
susceptible to these issues. Implementation: Sanity checks should be performed on all calculated values used as
index or for pointer arithmetic. | Demonstrative Examples | 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: C Example: int main() { ... strncpy(destBuf, &srcBuf[find(srcBuf, ch)], 1024); ... } If the index to srcBuf is somehow under user control, this is an arbitrary
write-what-where condition. | | Observed Examples | | Reference | Description |
|---|
| CVE-2002-2227 | Unchecked length of SSLv2 challenge value leads to buffer underflow. | | CVE-2007-4580 | Buffer underflow from a small size value with a large buffer (length parameter
inconsistency, CWE-130) | | CVE-2007-1584 | Buffer underflow from an all-whitespace string, which causes a counter to be
decremented before the buffer while looking for a non-whitespace character. | | CVE-2007-0886 | Buffer underflow resultant from encoded data that triggers an integer overflow. | | CVE-2006-6171 | Product sets an incorrect buffer size limit, leading to "off-by-two" buffer
underflow. | | CVE-2006-4024 | Negative value is used in a memcpy() operation, leading to buffer underflow. | | CVE-2004-2620 | Buffer underflow due to mishandled special characters |
| | Context Notes | 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. | | References | | | Relationships | | | Source Taxonomies | PLOVER - UNDER - Boundary beginning violation ('buffer underflow'
?) CLASP - Buffer underwrite | | Applicable Platforms | C C++ | | Time of Introduction | Implementation |
Weakness ID
| Status: Draft 126 (Weakness Variant) | | Description | Summary The software reads data past the end of the intended buffer. | | Weakness Ordinality | Primary (Weakness exists independent of other weaknesses) | | Causal Nature | Explicit (This is an explicit weakness resulting from behavior of the developer) | | Relationships | | | Source Taxonomies | PLOVER - Buffer over-read | | Applicable Platforms | C C++ | | Time of Introduction | Implementation |
Weakness ID
| Status: Draft 127 (Weakness Variant) | | Description | Summary The software reads data before the start of the intended buffer. | | Weakness Ordinality | Primary (Weakness exists independent of other weaknesses) | | Causal Nature | Explicit (This is an explicit weakness resulting from behavior of the developer) | | Research Gaps | Under-studied. | | Relationships | | | Source Taxonomies | PLOVER - Buffer under-read | | Applicable Platforms | C C++ | | Time of Introduction | Implementation |
Weakness ID
| Status: Draft 482 (Weakness Variant) | | Description | Summary The code uses an operator for comparison when the intention was to perform an assignment. Extended Description In many languages, the compare statement is very close in appearance to the assignment
statement; they are often confused. | | Likelihood of Exploit | Low | | Potential Mitigations | Pre-design: Through Build: Many IDEs and static analysis products will detect this
problem. | Demonstrative Examples | C/C++/Java Example: void called(int foo) { foo==1; if (foo==1) printf("foo\n"); } int main() { called(2); return 0; } | | Context Notes | This bug is mainly a typo and usually should cause obvious problems with program
execution. The assignment will not always take place. | | Relationships | | | Source Taxonomies | CLASP - Comparing instead of assigning | | Applicable Platforms | C C++ |
Weakness ID
| Status: Draft 396 (Weakness Base) | | Description | Summary Catching overly broad exceptions promotes complex error handling code that is more likely
to contain security vulnerabilities. | Demonstrative Examples | The following code excerpt handles three types of exceptions in an identical
fashion. try { doExchange(); } catch (IOException e) { logger.error("doExchange failed", e); } catch (InvocationTargetException e) { logger.error("doExchange failed", e); } catch (SQLException e) { logger.error("doExchange failed", e); } At first blush, it may seem preferable to deal with these exceptions in a single
catch block, as follows: try { doExchange(); } catch (Exception e) {
logger.error("doExchange failed", e); } However, if doExchange() is modified to throw a
new type of exception that should be handled in some different kind of way, the broad
catch block will prevent the compiler from pointing out the situation. Further, the new
catch block will now also handle exceptions derived from RuntimeException such as
ClassCastException, and NullPointerException, which is not the programmer's intent.
| | Context Notes | Multiple catch blocks can get ugly and repetitive, but "condensing" catch blocks by
catching a high-level class like Exception can obscure exceptions that deserve special treatment
or that should not be caught at this point in the program. Catching an overly broad exception
essentially defeats the purpose of Java's typed exceptions, and can become particularly dangerous
if the program grows and begins to throw new types of exceptions. The new exception types will not
receive any attention. | | Relationships | | | Source Taxonomies | 7 Pernicious Kingdoms - Overly-Broad Catch Block | | Applicable Platforms | C C++ Java .NET |
Weakness ID
| Status: Draft 397 (Weakness Base) | | Description | Summary Throwing overly broad exceptions promotes complex error handling code that is more likely
to contain security vulnerabilities. | Demonstrative Examples | The following method throws three types of exceptions. public void doExchange() throws IOException, InvocationTargetException, SQLException { ... } While it might seem tidier to write public void doExchange() throws Exception { ...
} doing so hampers the caller's ability to understand and handle the exceptions that
occur. Further, if a later revision of doExchange() introduces a new type of exception
that should be treated differently than previous exceptions, there is no easy way to
enforce this requirement. | | Context Notes | Declaring a method to throw Exception or Throwable makes it difficult for callers to do
good error handling and error recovery. Java's exception mechanism is set up to make it easy for
callers to anticipate what can go wrong and write code to handle each specific exceptional
circumstance. Declaring that a method throws a generic form of exception defeats this system. | | Relationships | | | Source Taxonomies | 7 Pernicious Kingdoms - Overly-Broad Throws Declaration | | Applicable Platforms | C C++ Java .NET |
Weakness ID
| Status: Incomplete 463 (Weakness Base) | | Description | Summary The accidental deletion of a data-structure sentinel can cause serious programming logic
problems. | | Common Consequences | 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. | | Potential Mitigations | Pre-design: Use a language or compiler that performs automatic bounds checking. Design: Use an abstraction library to abstract away risky APIs. Not a complete
solution. Pre-design through Build: 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. Operational: Use OS-level preventative functionality. Not a complete
solution. | Demonstrative Examples | C/C++ Example: char *foo; int counter; foo=malloc(sizeof(char)*10); for (counter=0;counter!=14;counter++) { foo[counter]='a'; printf("%s\n",foo); } | | Context Notes | 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, of course 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. | | Relationships | | | Source Taxonomies | CLASP - Deletion of data-structure sentinel | | Applicable Platforms | C C++ |
Weakness ID
| Status: Draft 415 (Weakness Variant) | | Description | Summary The product calls free() twice on
the same memory address, potentially leading to
modification of unexpected memory locations. | | Alternate Terms | Double-free | | Likelihood of Exploit | Low to Medium | | Affected Resource | Memory | | Common Consequences | Access control: Doubly freeing memory may result in a write-what-where
condition, allowing an attacker to execute arbitrary code. | | Potential Mitigations | 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. | Demonstrative Examples | Example 1: The following code shows a simple example of a double free vulnerability. 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. #include <stdio.h> #include <unistd.h> #define BUFSIZE1 512 #define BUFSIZE2 ((BUFSIZE1/2) - 8) int main(int argc, char **argv) { char *buf1R1; char *buf2R1; char *buf1R2; buf1R1 = (char *) malloc(BUFSIZE2); buf2R1 = (char *) malloc(BUFSIZE2); free(buf1R1); free(buf2R1); buf1R2 = (char *) malloc(BUFSIZE1); strncpy(buf1R2, argv[1], BUFSIZE1-1); free(buf2R1); free(buf1R2); } | | Observed Examples | | | Context Notes | 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. Also a Consequence. 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.
It could be argued that Double Free would be most appropriately located as a child of "Use after Free", but we're considering "Use" and "Release" to be distinct operations, therefore this is more accurately "Release of a Resource after Expiration or Release", which doesn't exist yet.
| | Relationships | | | Source Taxonomies | PLOVER - DFREE - Double-Free Vulnerability 7 Pernicious Kingdoms - Double Free CLASP - Doubly freeing memory | | Applicable Platforms | C C++ |
Weakness ID
| Status: Incomplete 462 (Weakness Base) | | Description | Summary Duplicate keys in associative lists can lead to non-unique keys being mistaken for an
error. | | Likelihood of Exploit | Low | | Potential Mitigations | Design: Use a hash table instead of an alist. Design: Use an alist which checks the uniqueness of hash keys with each entry before
inserting the entry. | | Context Notes | 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. In Python: 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. | | Relationships | | | Source Taxonomies | CLASP - Duplicate key in associative list (alist) | | Applicable Platforms | C C++ Java .NET |
Weakness ID
| Status: Draft 243 (Weakness Variant) | | Description | Summary When a product uses the chroot() system call to
create a jail, but does not change the working
directory afterward,
this might allow attackers to access files outside of the
jail. | | Likelihood of Exploit | High | | Weakness Ordinality | Resultant (Weakness is typically related to the presence of some other weaknesses) | | Causal Nature | Explicit (This is an explicit weakness resulting from behavior of the developer) | | Affected Resource | File/Directory | Demonstrative Examples | Example: Consider the following source code from a (hypothetical) FTP server: 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. | | Context Notes | 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. 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. | | Relationships | | | Source Taxonomies | 7 Pernicious Kingdoms - Directory Restriction | | Applicable Platforms | C C++ | | Time of Introduction | Implementation |
Weakness ID
| Status: Draft 244 (Weakness Variant) | | 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. | | Affected Resource | Memory | Demonstrative Examples | The following code calls realloc() on a buffer containing sensitive data: cleartext_buffer = get_secret(); ... cleartext_buffer = realloc(cleartext_buffer, 1024); ... scrub_memory(cleartext_buffer, 1024); 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. | | Context Notes | Heap inspection vulnerabilities occur when sensitive data, such as a password or an
encryption key, can be exposed to an attacker because they are not removed from memory. 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. Be careful using {vfork, fork} in security sensitive code. The process state will not
be cleaned up and will contain traces of data from past use. | | Relationships | | | Source Taxonomies | 7 Pernicious Kingdoms - Heap Inspection | | Applicable Platforms | C C++ | | Time of Introduction | Implementation |
Weakness ID
| Status: Draft 401 (Weakness Base) | | Description | Summary The software does not sufficiently track and release allocated memory after it has been
used, which slowly consumes remaining memory. This is often triggered by improper handling of
malformed data or unexpectedly interrupted sessions. | | Functional Area | Memory management | | Likelihood of Exploit | Medium | | Affected Resource | Memory | | Common Consequences | Availability: If an attacker can determine the cause of the memory leak, then
the attacker may be able to cause the application to leak quickly and therefore cause the
application to crash. | | Potential Mitigations | Pre-design: Use a language or compiler that performs automatic bounds checking. 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. | 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: C Example: 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: In C: C Example: bar connection(){ foo = malloc(1024); return foo; } endConnection(bar foo) { free(foo); } int main() { while(1) //thread 1 //On a connection foo=connection(); //thread 2 //When the connection ends endConnection(foo) } } 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. | | Observed Examples | | Reference | Description |
|---|
| CVE-2005-3119 | Memory leak because function does not free() an element of a data structure. | | CVE-2004-0427 | Memory leak when counter variable is not decremented. | | CVE-2002-0574 | Memory leak when counter variable is not decremented. | | CVE-2005-3181 | Kernel uses wrong function to release a data structure, preventing data from being
properly tracked by other code. | | CVE-2004-0222 | Memory leak via unknown manipulations as part of protocol test suite. | | CVE-2001-0136 | Memory leak via a series of the same command. |
| | Context Notes | This is often a resultant weakness due to improper handling of malformed data or early
termination of sessions. Terminology Note: "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). 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 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 the program) or take advantage of other unexpected program behavior
resulting from a low memory condition [30]. | | References | [30] J. Whittaker and H. Thompson.
"How to Break Software Security". Addison Wesley. 2003. | | Relationships | | | Source Taxonomies | PLOVER - Memory leak 7 Pernicious Kingdoms - Memory Leak CLASP - Failure to deallocate data | | Applicable Platforms | C C++ | | White Box Definition | 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. identity of the dynamic allocated memory resource obtained but got re-written (missing beyond recovery) 3. identity of the dynamic allocated memory resource obtained but never passed on to function for memory resource release 4. the statement assigns another value to the last data element that stored the identity of the dynamically allocated memory resource (no more aliases remain) 5. the last data element that stored the identity of the dynamically allocated resource has reached the end of its scope at the statement
|
Weakness ID
| Status: Draft 478 (Weakness Variant) | | Description | Summary The failure to account for the default case in switch statements may lead to complex
logical errors and may aid in other, unexpected security-related conditions. | | Common Consequences | Undefined: Depending on the logical circumstances involved, any consequences
may result: e.g., issues of confidentiality, authentication, authorization, availability,
integrity, accountability, or non-repudiation. | | Potential Mitigations | Implementation: Ensure that there are no unaccounted for cases, when adjusting flow or
values based on the value of a given variable. In switch statements, this can be accomplished
through the use of the default label. | Demonstrative Examples | In general, a safe switch statement has this form: switch (value) { case 'A': printf("A!\n"); break; case 'B': printf("B!\n"); break; default: printf("Neither A nor B\n"); } This is because the assumption cannot be made that all possible cases are accounted
for. A good practice is to reserve the default case for error handling. | | Context Notes | This flaw represents a common problem in software development, in which not all
possible values for a variable are considered or handled by a given process. Because of this,
further decisions are made based on poor information, and cascading failure results. This
cascading failure may result in any number of security issues, and constitutes a significant
failure in the system. In the case of switch style statements, the very simple act of creating a
default case can mitigate this situation, if done correctly. Often however, the default cause is
used simply to represent an assumed option, as opposed to working as a sanity check. This is poor
practice and in some cases is as bad as omitting a default case entirely. | | Relationships | | | Source Taxonomies | CLASP - Failure to account for default case in switch | | Applicable Platforms | C C++ Java .NET |
Weakness ID
| Status: Draft 122 (Weakness Variant) | | Description | Summary 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(). | | Likelihood of Exploit | High to Very High | | Weakness Ordinality | Primary (Weakness exists independent of other weaknesses) | | Causal Nature | Explicit (This is an explicit weakness resulting from behavior of the developer) | | Affected Resource | Memory | | Common Consequences | 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 (memory and instruction processing): Buffer overflows often can
be used to execute arbitrary code, which is usually outside the scope of a program's implicit
security policy. Other: When the consequence is arbitrary code execution, this can often be
used to subvert any other security service. | | Potential Mitigations | Pre-design: Use a language or compiler that performs automatic bounds checking. 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. Operational: Use OS-level preventative functionality. Not a complete
solution. | Demonstrative Examples | C Example: #define BUFSIZE 256 int main(int argc, char **argv) { char *buf; buf = (char *)malloc(BUFSIZE); strcpy(buf, argv[1]); } | | Observed Examples | | Reference | Description |
|---|
| CVE-2007-4268 | Chain: integer signedness passes signed comparison, leads to
heap overflow |
| | Context Notes | Heap-based buffer overflows are usually just as dangerous as stack-based buffer
overflows. 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. | | Relationships | | | Source Taxonomies | CLASP - Heap overflow | | Applicable Platforms | C C++ | | Time of Introduction | Implementation | | Related Attack Patterns | | CAPEC-ID | Attack Pattern Name |
|---|
| 92 | Forced Integer Overflow |
| | White Box Definition | A buffer overflow where the buffer from the Buffer Write Operation is dynamically allocated
|
Weakness ID
| Status: Draft 460 (Weakness Variant) | | Description | Summary The product does not sufficiently
clean up its state when an exception is thrown, leading to
unexpected state or control flow. | | Likelihood of Exploit | Medium | | Common Consequences | Implementation: The code could be left in a bad state. | | Potential Mitigations | 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. | Demonstrative Examples | C++/Java Example: 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. | | Context 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. | | Relationships | | | Source Taxonomies | CLASP - Improper cleanup on thrown exception | | Applicable Platforms | C C++ Java .NET |
Weakness ID
| Status: Incomplete 170 (Weakness Base) | | Description | Summary The software does not properly terminate a string or array with a null character or
equivalent terminator. 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. | | Likelihood of Exploit | High | | Potential Mitigations | If performance constraints permit, special code can be added that validates
null-termination of string buffers, this is a rather naïve and error-prone solution. Switch to bounded string manipulation functions. Inspect buffer lengths involved in
the buffer overrun trace reported with the defect. 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). | 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. #define MAXLEN 1024 ... char *pathbuf[MAXLEN]; ... read(cfgfile,inputbuf,MAXLEN); //does not null terminate strcpy(pathbuf,input_buf); //requires null terminated input ... The code in Example 1 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(). ... char buf[MAXPATH]; ... readlink(path, buf, MAXPATH); int length = strlen(filename); ... The code in Example 2 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. | | Observed Examples | | Reference | Description |
|---|
| CVE-2000-0312 | Attacker does not null-terminate argv[] when invoking another program. | | CVE-2003-0777 | Interrupted step causes resultant lack of null termination. | | CVE-2004-1072 | Fault causes resultant lack of null termination, leading to buffer expansion. | | CVE-2001-1389 | Multiple vulnerabilities related to improper null termination. | | CVE-2003-0143 | Product does not null terminate a message buffer after snprintf-like call, leading to
overflow. |
| | Context Notes | Conceptually, this does not just apply to the C language; any language or
representation that involves a terminator could have this sort of problem. 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. | | Relationships | | | Source Taxonomies | PLOVER - Improper Null Termination 7 Pernicious Kingdoms - String Termination Error | | Applicable Platforms | C C++ | | White Box Definition | 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 removes the null-terminator from the data item Where “removes” is defined through the following scenarios: 1. data item never ended with null-terminator 2. null-terminator is re-written
|
|