The program relies on proper string termination, but an intermediate function might have caused the source buffer to become unterminated. This could result in a buffer overflow.
String termination errors caused by truncation occur when:
1. Data enters a program.
2. The data passes through a function that truncates it, removing the null terminator.
3. The data is passed to a function that requires its input to be null terminated.
Example 1: The following code retrieves the value of a null-terminated environment variable and uses strncpy()
to copy the data into new
. Later, the program incorrectly assumes new
will always be null terminated when it is passed to setenv()
.
...
char *value = getenv("PWD");
...
char *new_value = strncpy(new, value, strlen(value));
setenv("PATH", new, 1);
...
strncpy()
is bounded by the length of the string as computed by strlen()
, which does not account for the null terminator, new
will become unterminated and cause the call to setenv()
to behave incorrectly. The function setenv()
will continue copying from the memory following new
until it encounters an arbitrary null character. If the function does not find a null terminator before reaching the maximum size of the program's environment, the behavior of the function and other environment functions is undefined. Even if an arbitrary null character is found, the PATH
environment variable might be left pointing to invalid directories. Worse yet, if the attacker can control values in memory that follow new
, then they might introduce malicious entries to PATH
, thereby changing the meaning of commands executed subsequently. fgets()
retrieves data from a stream and stores it in buf
. The function guarantees that the data will not exceed the buffer size and that the result is null terminated. Later, strncpy()
is used to copy a subset of the data to a new buffer, data
. The length of the resulting value is then calculated using strlen()
....
char buf[MAXLEN];
fgets(buf, MAXLEN, stream);
...
strncpy(data, buf, data_size);
...
int length = strlen(data);
...
data_size
is less than or equal to the length of data read from the stream because the null terminator will not be copied to data
. In testing, vulnerabilities like this one might not be caught because the memory immediately following data
will often be null, thereby causing strlen()
to produce the correct answer accidentally. However, in practice, strlen()
will continue traversing memory until it encounters an arbitrary null character on the stack, which can result in a value of length
that is much larger than the size of buf
. Subsequent operations on data
that rely on length
might result in buffer overflow.[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, APP3590.1 CAT I
[3] Standards Mapping - Web Application Security Consortium 24 + 2 - (WASC 24 + 2) Buffer Overflow
[4] Standards Mapping - Common Weakness Enumeration - (CWE) CWE ID 170
[5] Standards Mapping - Payment Card Industry Data Security Standard Version 1.2 - (PCI 1.2) Requirement 6.3.1.1
[6] Standards Mapping - Payment Card Industry Data Security Standard Version 2.0 - (PCI 2.0) Requirement 6.5.2
[7] Standards Mapping - Payment Card Industry Data Security Standard Version 1.1 - (PCI 1.1) Requirement 6.5.5
[8] Standards Mapping - SANS Top 25 2009 - (SANS 2009) Risky Resource Management - CWE ID 665
[9] Standards Mapping - SANS Top 25 2010 - (SANS 2010) Risky Resource Management - CWE ID 665
[10] M. Howard, D. LeBlanc Writing Secure Code, Second Edition Microsoft Press