The 3 Types of Buffer Overflow Attacks and Prevention Tips 
T

The 3 Types of Buffer Overflow Attacks and Prevention Tips 

Written By Nazifa Alam

Types of Buffer Flow Attacks 

The various types of buffer overflow attacks listed below are some common methods attackers may use to target an organisation:  

  1. Stack-based attacks – Which is the most common form of a buffer overflow attack. This form of attack involves the attacker(s) sending a data packet embedded with a malicious code to an application which is then stored into a stack buffer. The data already present on the stack is then overwritten by the malicious code causing the control of the device to be transferred to the attacker.  
  1. Heap-based attacks – This type of attack is more difficult to execute as it involves flooding a program’s memory space. This line of attack is also more time consuming and expensive to commit.  
  1. Format string attack – This form of attack involves an application processing input data as a command. Due to this, the attacker is able to read data in the stack, execute a code or cause segmentation faults in the application.  

What Programming Languages are more Susceptible?  

The two languages that are more vulnerable to buffer overflow attacks are C and C++ due to their absence of inbuilt safeguarding features against overwriting or illegitimate access of data in their memory. Mac OSX, Windows and Linux all use C and C++ languages. A buffer overflow in Assembly, C, C++ or Fortran is more likely to lead to a compromised system at the hands of an attacker. 

Languages including PERL, Java, JavaScript and C# are less vulnerable to buffer overflow attacks due to their in-built safety features.  

Detecting Buffer Overflow Attacks  

The important practice is to keep note of where buffers are used, modified and accessed. More specifically, the functions dealing with the input provided by the user or an external source would be the more likely area to be exploited by an attacker.  

For example, highlighted below, a command that requires a simple yes or no input will have reserved a small buffer space only for a single word answer.  

If the user inputs ‘maybe’, the program will instead stop working rather than allowing the user another chance to enter a valid answer. The original, invalid answer is stored into the buffer, regardless of its length. If the user enters an answer that takes a certain number of bytes followed by a valid address in memory, the program’s return address will be changed. This will then enable the attacker to force an exit at a different point in the code than originally intended, leading to high levels of instability. 

Other examples of buffer overflow attacks 

A simple buffer overflow attack as a result of a ‘gets()’ function being externally sent to a stack buffer: 

“… 

char buf [BUFSIZE] 

gets(buf); 

…” 

The data cannot be limited and therefore, there is a reliance upon users entering fewer characters than ‘BUFSIZE’ characters.  

In some cases, buffer overflow attacks rely on the user input to control functions and then cause errors through ‘memcpy()’, the memory function. The destination buffer, source buffer and the amount of bytes needed to copy is then enabled and the input buffer can be filled with the ‘read()’ command in addition to a specific allocation of bytes for ‘memcpy()’. Below is a display: 

“… 

char buf[64], in[MAX_SIZE]; 

printf(“Enter buffer contents:\n”); 

read(0, in, MAX_SIZE-1); 

printf(“Bytes to copy:\n”); 

scanf(“%d”, &bytes); 

memcpy(buf, in, bytes); 

…” 

Another instance of a buffer overflow attack could be the case of the data lacking local verification. The function ‘lccopy()’ is responds to a string with uppercase letters in place of lowercase letters. Bound checking is not executed as ‘str’ is expected to be smaller that ‘BUFSIZE’. Due to this, the attacker can change the expected size according to their wish or bypass the code.  

An example of this instance is as followed: 

“char *lccopy(const char *str) { 

char buff[BUFSIZE]; char *p; 

strcpy(buf, str); 

for (p=buf; *p; p++) { 

if (isupper(*p)) { 

*p=tolower(*p); 

   } 

Return strdup(buf); 

}” 

Buffer overflow attacks can also occur when the code is too complex for a prediction to be made. The code below is an example from the linPNG image decoder which is programmed into the browsers Mozilla and Internet Explorer. The example shows a safe, legitimate code becoming more complicated due to the execution of a ‘png_ptr->mode’ review. To reduce the waste of memory, the complexity of the code should be kept at minimum.  

“if (!(png_ptr->mode & PNG_HAVE_PLTE)) { 

/*Should be an error, but we can cope with it */ 

png_warning(png_ptr, “Missing PLTE before tRNS”);} 

else if (length > (png_uint_32png_ptr->num_palette) { 

png_warning(png_ptr, “Incorrect tRNS chunk length”); 

png_crc_finish(png_ptr, length); 

return; 

… 

png_crc_read(png_ptr, readbuf, (png_size_t)length);” 

Preventing Buffer Overflow Attacks  

One of the simplest measures against these exploits is simply to use a programming language that does not allow them. As mentioned earlier in this article, C and C++ both contain increased vulnerability rates however Java, Python and .NET do not.  

Upon initial observation, using strn- which only writes to the maximum size of the target buffer may seem like a viable option. This however, may lead to more problems as if the buffer limit is reached without a terminating character being placed before the buffer limit, difficulties will arise. Below is an example of this: 

When ‘foo’ is entered into (normal_buffer), it is null terminated due to additional buffer space. With the case of (full_buffer) however, where there is no available buffer space for the entry, the results are as followed: 

Although the entry in (normal_buffer) has been correctly printed, an extra character has been printed in (full_buffer). If the next bytes were composed of a printable string, the print function would have continued until the terminating character. 

OpenBDS provides the use of strlcpy and strlcat which although provides similar functions to the strn-functions, terminates the string one character early to allow space for the null terminator. Microsoft provides safety alternatives to commonly exploited functions such as strcpy_s, strcat_s and sprint_s.  

The safer alternatives are as followed: 

  • strlcpy*, strcpy_s* 
  • strlcat*, strcat s* 
  • snprintf*, sprint_s* 
  • fgets 

Nowadays, modern operating systems are equipped with runtime protection. Nevertheless, it is beneficial to adopt the following practices for protection: 

  • Address Space Randomisation (ASLR) –Buffer overflow attacks are commonly successful due to the attacker’s previous knowledge concerning the locality of the executable code and by randomising address spaces, the attacks become limited.  
  • Data Execution Prevention – Which determines certain areas of memory as executable or not, preventing a code from being ran in a non-executable region.  
  • Structured Exception Handler Overwrite Protection (SEHOP) – This is a built-in function which oversees hardware and software anomalies. Therefore, SEHOP prevents an attacker from having the ability to perform the SHE exploitation which involves overwriting the system.  

Stay up to date with the latest threats

Our newsletter is packed with analysis of trending threats and attacks, practical tutorials, hands-on labs, and actionable content. No spam. No jibber jabber.