Buffer Overflow (BOF) Examples
CVE-2014-0160 (Heartbleed)
BF Taxonomy
Cause:
Input not checked properly leads to Data Exceeds Array (specifically
Too Much Data)
Consequence:
IEX (if not had been cleared - CWE-226)
BF Description
"Input not checked properly leads to too much data, where
huge data is read from the heap in a
continuous excursion above the array boundary, which may be exploited for
IEX (if not had been cleared)." [2]
CVE Description
"The (1) TLS and (2) DTLS implementations in OpenSSL 1.0.1 before 1.0.1g do not properly handle Heartbeat
Extension packets, which allows remote attackers to obtain sensitive information from process memory via crafted
packets that trigger a buffer over-read, as demonstrated by reading private keys, related to d1_both.c and
t1_lib.c, aka the Heartbleed bug." [1]
Analysis
The following analysis is based on information in [1,3,4,5]. A user has to send to the
software data, and a number called payload that is the length of that data. The software has to send the
data received back to the user. In the Heartbleed attack, a malicious user gives payload a value that can
be as large as 65535+1+2+16, and sends data having a number of bytes that is much less than payload, and can be
as small as 1. The software stores that data in an array that it allocated for that purpose. The size of that
array is much less than 65535+1+2+16. The software does not check the data and the value of payload in
order to make sure that the number of bytes of data is equal to payload. The software therefore assumes that
those numbers are equal. The software reads, using memcpy, payload consecutive bytes from that array,
beginning at its first byte, (continuous excursion) and sends them to the malicious user.
This results in reading a large number of bytes beyond the end of the allocated array. The software did not
clear the memory that it read from beyond the allocated array. Therefore, the data read and sent to the
malicious user by the software includes sensitive information.
Source Code
CVE-2015-0235 (Ghost)
BF Taxonomy
Cause:
Incorrect Calculation (Missing Factor) leads to Array Too Small
Consequence:
Arbitrary Code Execution leading to DoS
BF Description
"Incorrect calculation (missing factor) leads to array too
small, where some data is written to the
heap in a continuous excursion above the array
boundary, which may be exploited for arbitrary code execution, leading to
DoS." [2]
CVE Description
"Heap-based buffer overflow in the __nss_hostname_digits_dots function in glibc 2.2, and other 2.x versions
before 2.18, allows context-dependent attackers to execute arbitrary code via vectors related to the (1)
gethostbyname or (2) gethostbyname2 function, aka GHOST." [6]
Analysis
The following analysis is based on information in [6,7,8]. The number of bytes that can be
overwritten is sizeof (char *), which is 4 bytes on a 32 bit machine, and 8 bytes on a 64 bit machine. In a
calculation of the size needed to store certain data, the size of a char pointer is missing, resulting in
array too small. Buffer over write is done by strcpy (continuous
excursion). Qualys developed an attack on the Exim mail server, exploiting this vulnerability, as proof of
concept. This attack uses an initial buffer over write to enlarge the number in the size field of a portion of
memory that is available for the next allocation. This modification enables a subsequent over write that enables
write-anything-anywhere, which in turn enables over writing Exim's Access Control Lists, which in turn enables
arbitrary code execution.
Source Code
Code With Bug |
1 2 3 4 5 6 7
|
/* calculate size incorrectly*/ size_needed = (sizeof (*host_addr)+ sizeof (*h_addr_ptrs) + strlen (name) + 1);
host_addr = (host_addr_t *) *buffer; h_addr_ptrs = (host_addr_list_t *)(( char *) host_addr + sizeof (*host_addr)); hostname = (char *) h_addr_ptrs + sizeof (*h_addr_ptrs); resbuf->h_name = strcpy (hostname, name);
|
|
Code With Fix |
1 2 3 4 5 6 7
|
/* calculate size incorrectly*/ size_needed = (sizeof (*host_addr) + sizeof (*h_addr_ptrs) + sizeof (*h_alias_ptr) + strlen (name) + 1);
host_addr = (host_addr_t *) *buffer; h_addr_ptrs = (host_addr_list_t *)((char*) host_addr + sizeof (*host_addr)); hostname = (char*) h_addr_ptrs + sizeof (*h_addr_ptrs); resbuf->h_name = strcpy (hostname, name);
|
|
CVE-2010-1773 (Chrome WebCore)
BF Taxonomy
Cause:
Incorrect calculation, (off by one) leads to a wrong index
Consequence:
Information exposure, arbitrary code execution or
program crash, leading to DoS
BF Description
"Incorrect calculation, (off by one) leads to a wrong index
, where little data is read from the heap
in a discrete excursion below the array boundary, which may be
exploited for information exposure, arbitrary code execution
or program crash, leading to DoS." [2]
CVE Description
"Off-by-one error in the toAlphabetic function in rendering/RenderListMarker.cpp in WebCore in WebKit before
r59950, as used in Google Chrome before 5.0.375.70, allows remote attackers to obtain sensitive information,
cause a denial of service (memory corruption and application crash), or possibly execute arbitrary code via
vectors related to list markers for HTML lists, aka rdar problem 8009118." [9]
Analysis
The following analysis is based on information in [9,10,11,12,13,14,15,16].The software
reads in a loop from an array, where the sequence of indices of array elements read is neither necessarily
monotonic nor necessarily having a fixed distance between consecutive elements. That index should be the
remainder obtained by dividing an integer by an integer. The software subtracts 1 from that remainder, which is
wrong, and can result in the index being equal to -1, leading to reading from an address that is below the
beginning of the array by 1. Consequences are mentioned in [10], and [16]
includes "An off by one memory read out of bounds issue exists in WebKit's handling of HTML lists. Visiting a
maliciously crafted website may lead to an unexpected application termination or the disclosure of the contents
of memory."
Source Code
CVE-2015-2282
BF Taxonomy
Cause:
Input not checked properly leads to wrong index
Consequence:
Arbitrary code execution or program crash, which can lead
to DoS
BF Description
"_INPut not checked properly leads to wrong index, where some
data is written to the heap in a
continuous excursion, above the array boundary, which can cause
arbitrary code execution or program crash, which can lead
to DoS." [19]
CVE Description
"Stack-based buffer overflow in the LZC decompression implementation (CsObjectInt::CsDecomprLZC function in
vpa106cslzc.cpp) in SAP MaxDB 7.5 and 7.6, Netweaver Application Server ABAP, Netweaver Application Server Java,
Netweaver RFC SDK, GUI, RFC SDK, SAPCAR archive tool, and other products allows context-dependent attackers to
cause a denial of service (crash) or possibly execute arbitrary code via unspecified vectors, aka SAP Security
Note 2124806, 2121661, 2127995, and 2125316." [17]
Analysis
[17, 18, 19, 20] include sufficient information for describing this CVE using BF. Note that
this buffer resides in the Heap even though it implements a stack data structure.
Source Code
Code With Bug |
Code With Fix |
Source Code Not Available
|
|
Source Code Not Available
|
|
CVE-2015-2278
BF Taxonomy
Cause:
Input not checked properly leads to wrong index
BF Description
"_INPut not checked properly leads to wrong index, where some
data is read in a discrete excursion,
above or below the array boundary, which can lead to DoS
."
CVE Description
"The LZH decompression implementation (CsObjectInt::BuildHufTree function in vpa108csulzh.cpp) in SAP MaxDB
7.5 and 7.6, Netweaver Application Server ABAP, Netweaver Application Server Java, Netweaver RFC SDK, GUI, RFC
SDK, SAPCAR archive tool, and other products allows context-dependent attackers to cause a denial of service
(out-of-bounds read) via unspecified vectors, related to look-ups of non-simple codes, aka SAP Security Note
2124806, 2121661, 2127995, and 2125316." [21]
Analysis
[18, 21, 22] include sufficient information for describing this CVE using BF.
Source Code
Code With Bug |
Code With Fix |
Source Code Not Available
|
|
Source Code Not Available
|
|
CVE-2018-19842
BF Taxonomy
Cause:
Boundary Not Checked Properly leads to Pointer Out of Range
Attributes:
Data Size: Small (1 byte)
Consequence:
Program Crash leading to DoS
BF Description
"Boundary Not Checked Properly leads to Pointer Out of Range, where
small data is read in a continuous excursion,
above the array boundary, which can lead to a Program Crash
leading to DoS."
CVE Description
"getToken in libr/asm/p/asm_x86_nz.c in radare2 before 3.1.0 allows attackers to cause a denial of service
(stack-based buffer over-read) via crafted x86 assembly data, as demonstrated by rasm2."
Analysis
In the assemble()
function, char op[128]
is defined, filled with the first 127 characters of the passed rasm2
command arguments, and
terminated with 0 (for to make a valid C string). So, there is no problem there.
However, in the getToken()
function, the part that skips spaces in str
, does no
check if the pointer bypasses the 0 terminator. The problem is only when the spaces go up to the end of
str
. If there were even only one character after the skipped spaces and before the end of
str
, the code works fine.
So, the 0 terminator is skipped only if while skipping spaces the last element in str
is a space
-- it could be only one space that is also the last one as in the Steps To Reproduce here.
The main fixes
check if whether the pointer reaches or bypasses the end of the string (buffer) :
if (*begin > strlen (str))
Note: There are still problems in the fixed code, as *begin
and *end
, are
used before checking if they are null
-- see lines 4298, 4307, 4311, 4318. If the assumption is
they are never null
, then why such a check is present in the while
loops.
Source Code
Code With Bug |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
static x86newTokenType getToken(const char *str, size_t *begin, size_t *end) {
while (begin && isspace ((ut8)str[*begin])) {
++(*begin);
}
if (!str[*begin]) { // null byte
*end = *begin;
return TT_EOF;
} else if (isalpha ((ut8)str[*begin])) { // word token
*end = *begin;
while (end && isalnum ((ut8)str[*end])) {
++(*end);
}
return TT_WORD;
} else if (isdigit ((ut8)str[*begin])) { // number token
*end = *begin;
while (end && isalnum ((ut8)str[*end])) { // accept alphanumeric characters, because hex.
++(*end);
|
|
Code With Fix |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
static x86newTokenType getToken(const char *str, size_t *begin, size_t *end) {
if (*begin > strlen (str)) {
return TT_EOF;
}
while (begin && str[*begin] && isspace ((ut8)str[*begin])) {
++(*begin);
}
if (!str[*begin]) { // null byte
*end = *begin;
return TT_EOF;
}
if (isalpha ((ut8)str[*begin])) { // word token
*end = *begin;
while (end && str[*end] && isalnum ((ut8)str[*end])) {
++(*end);
}
return TT_WORD;
}
if (isdigit ((ut8)str[*begin])) { // number token
*end = *begin;
while (end && isalnum ((ut8)str[*end])) { // accept alphanumeric characters, because hex.
++(*end);
|
|
References
[1] The MITRE Corporation, CVE Common Vulnerabilities and Exposures, CVE-2014-0160.
[6] The MITRE Corporation, CVE Common Vulnerabilities and Exposures, CVE-2015-0235.
[9] The MITRE Corporation, CVE Common Vulnerabilities and Exposures, CVE-2010-1773.
[12] chromium, Diff of /branches/WebKit/375/WebCore/rendering/RenderListMarker.cpp. Revision
48099.
[13] chromium, Contents of /branches/WebKit/375/WebCore/rendering/RenderListMarker.cpp.
Revision
44321.
[14] chromium, Contents of /branches/WebKit/375/WebCore/rendering/RenderListMarker.cpp. Revision
48100.
[17] The MITRE Corporation, CVE Common Vulnerabilities and Exposures, CVE-2015-2282.
[21] The MITRE Corporation, CVE Common Vulnerabilities and Exposures, CVE-2015-2278.