The program uses an improperly bounded format string, allowing it to write outside the bounds of allocated memory. This behavior could corrupt data, crash the program, or lead to the execution of malicious code.
Buffer overflow is probably the best known form of software security vulnerability. Most software developers know what a buffer overflow vulnerability is, but buffer overflow attacks against both legacy and newly-developed applications are still quite common. Part of the problem is due to the wide variety of ways buffer overflows can occur, and part is due to the error-prone techniques often used to prevent them.
In a classic buffer overflow exploit, the attacker sends data to a program, which it stores in an undersized stack buffer. The result is that information on the call stack is overwritten, including the function's return pointer. The data sets the value of the return pointer so that when the function returns, it transfers control to malicious code contained in the attacker's data.
Although this type of stack buffer overflow is still common on some platforms and in some development communities, there are a variety of other types of buffer overflow, including heap buffer overflows and off-by-one errors among others. There are a number of excellent books that provide detailed information on how buffer overflow attacks work, including Building Secure Software [1], Writing Secure Code [2], and The Shellcoder's Handbook [3].
At the code level, buffer overflow vulnerabilities usually involve the violation of a programmer's assumptions. Many memory manipulation functions in C and C++ do not perform bounds checking and can easily exceed the allocated bounds of the buffers they operate upon. Even bounded functions, such as strncpy()
, can cause vulnerabilities when used incorrectly. The combination of memory manipulation and mistaken assumptions about the size or makeup of a piece of data is the root cause of most buffer overflows.
In this case, an improperly constructed format string causes the program to write beyond the bounds of allocated memory.
Example: The following code overflows c
because the double
type requires more space than is allocated for c
.
void formatString(double d) {
char c;
scanf("%d", &c)
}
[1] Standards Mapping - OWASP Top 10 2004 - (OWASP 2004) A5 Buffer Overflow
[2] Standards Mapping - Security Technical Implementation Guide Version 3 - (STIG 3) APP3510 CAT I, APP3560 CAT I, APP3590.1 CAT I
[3] J. Viega, G. McGraw Building Secure Software Addison-Wesley
[4] Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 787, CWE ID 134
[5] Standards Mapping - Web Application Security Consortium 24 + 2 - (WASC 24 + 2) Format String Attack
[6] Standards Mapping - Payment Card Industry Data Security Standard Version 1.2 - (PCI 1.2) Requirement 6.3.1.1
[7] Standards Mapping - Payment Card Industry Data Security Standard Version 2.0 - (PCI 2.0) Requirement 6.5.2
[8] Standards Mapping - Payment Card Industry Data Security Standard Version 1.1 - (PCI 1.1) Requirement 6.5.5
[9] Standards Mapping - SANS Top 25 2009 - (SANS 2009) Risky Resource Management - CWE ID 119
[10] J. Koziol et al. The Shellcoder's Handbook: Discovering and Exploiting Security Holes John Wiley & Sons
[11] M. Howard, D. LeBlanc Writing Secure Code, Second Edition Microsoft Press