Defeating integer overflow attack
This article unleashes memory overflow related security vulnerabilities, in particular, Integer Overflow (resided during source coding inadvertently) in software as the number of identification of such bug has been increasing rapidly in the industry and exploited by a hacker for vicious intention. Both Integer Overflow and Format String bugs can be used to accomplish a range of strikes, from crashing a program to taking full control of it. Overall, we shall experience how integer overflow vulnerabilities can be used to overflow memory buffers by hackers, as well as detection mechanism used for the identification of integer overflow bug in the executable.
As Integer and Buffer overflow vulnerability typically occurs in C/C++ code compiled binary. Therefore adroitness in such programming language is required along with assembly language instruction sets understanding.
1. Buffer overrun
Buffer overrun takes place when the input is larger than the space allocated for it, and memory is written outside the space allocated for it. Buffer overrun and integer overflow issues are two aspects of the same coin in some extent, in fact, group with “overflow” where malicious code try to be executed beyond the allocated buffer size without acquaintance of program in elevated privilege scenario. However, buffer overflows issues are quite a rate as high-level languages does not have direct access to memory. As an analogy, if your code allocates ‘n’ bytes for a buffer, and your code copies more than ‘n’ bytes to the buffer then the buffer will overrun and your program yields strange result. The motive behind this vicious attack is to change the flow of execution in the application. Hackers, in this quest, manipulates the program behavior in its own determined goals. Also, attackers could only add user accounts if the code that contains the buffer overflow is running with high privileges. Hence as a buffer overrun defense, it is highly suggestive, never ever run code with elevated privileges unless you need it so. Second, don’t trust inputs, always validate incoming buffers to make sure that buffer in correct size instead.
2. Integer data type
An integer is a data type in programming that can hold numeric values and does not support fraction form. Furthermore, it has the ability to determine that the store value is either a positive or negative number by categorizing it into Signed and Unsigned. Signed integer store either a 1 or 0 in the most
Significant bit (MSB) of their first byte where 1 represents to Positive value and 0 is for Negative value. Unsigned integer, on the other hand, is positive by default because it does not consume MSB bit at all.
Similarly, the short integer type is a signed data type that holds 2 bytes worth of data as illustrated in the figure above in which each zero represents one bit in this unsigned short data representation. Furthermore, in case of signed short data representation, the leftmost zero signifies the high-order but in the signed short data depiction as following.
The high-order bit indicates whether the number is positive or negative. With 15 bits, 32768 (2 ^ 15) numbers can be represented. The 16-bit data type can only store a maximum value of 32,767, whereas a 32-bit data type can store a maximum value of 2,147,483,647. Therefore, if 16- bit signed data type assigned a value of 60,000 then an integer overflow would definitely occur and program behave in an unexpected way.
3. Integer overflow bug
Integer overflow or boundary condition results when the numeric data type designated to handle an operation fails to handle the data when input extends beyond the limit for that data type and eventually produce an unexpected outcome. If the computer is being direct to store the number in a short integer type. What happens when the calculation 25000 + 25000 is done? Let’s consider the following code snippets and conceive about the output?
Code Listing 1.1
Though this code successfully compiles but will produce an unexpected result as -155536 because such addition is too big a number to fit in 15 bits. Therefore math overflows and the sign will be changed. This buffer or numeric overflow bug is presuming as a code level defect, typically emerges in those software’s that’s source code written in C and C++ programming. Whereas, code written in a .Net language on the other hand, controlled or executed by the Common Language Runtime which provides an abstraction layer for memory and object management functions and furthermore, preventing vulnerabilities, such as buffer overflows, integer overflows, and format string vulnerabilities, occurred due to poor memory management. Integer overflows appear because the values stored in integer type limited by the size of the data type itself. Let’s consider the following code as;
Code Listing 1.2
At first glance, the code above looking simple, it checks the incoming data is no larger than the destination buffer, adding two integers together. Imagine that the first variable is 0x98 and the second variable is 0xEEEEEEEC, and then output is bizarre as following;
This is conceptually overflowing memory all the way. Now, take a closure look at this code for more understanding, which is, however, analog to the earlier sample:
Code Listing 1.3
Although, the code above seems to be pretty simple, as well as behave as expectedly but the movement, user input is beyond the limit (7), program halted as because of memory reading violation access at location 0x567FF7B3 as following;
So, an integer value is increased to a value that is the maximum allowed value, end up in either negative number or a small number, instead of the expected large value. Furthermore, there is another type of integer-related attack is truncation, in which code performs buffer allocations using short data type, such as short int. Look at the following code:
Code Listing 1.4
In this sample, the code is allocating space based on a 16-bit short integer, but the actual memory copy is being made using a 32-bit size_t, which is literally an indication of potential truncation bug, where more data than the allocated could be copied in the buffer.
4. Defeating attack
Lack of programming practices is typically the root cause of occurring integer overflows bugs. Some of best are being suggested to mitigate integer overflow attack, first never trust the numbers being manipulated if they come from an untrusted source. Second, never use signed integer for array indexing or memory allocation. A simple way to make sure the results have not overflowed is to replace code in code listing 1.2 as:
Third, it is highly recommended for looking or auditing for known dangerous function such as strcpy, memcpy, etc… inner structure by duly ensuring lest they are processing problematic code. It is, however, hard to construct test data that has a length of various powers of two, and slowly grow integer overflow from each, especially for 32-bit signed and unsigned value. But, despite the sophistication, hackers somehow sustain to perform these attacks. Finally, proper code reviewing especially while testing and deep understanding of how the programming language works could probably defeat such bugs to be occurring because it is ultimately the testing that is accountable for buggy shipped products.
A programming language that enables direct memory access and those that do not provision to bound validation on buffers and numeric operation are particularly vulnerable to buffer and integer overflow attacks. Integer overflow often leads to a buffer overflow in which integer overflows occur when computing the size of the memory to allocate. In this article, it was being presented overflow related bugs in details, particularly overrun. However, buffer overflow bug explication is beyond the scope of this paper except for brief outline. Overall, integer overflow aggregately occurs when a register or specific data type meant to hold value within a certain range is assigned a value outside that range.