Buffer overflow: causes, effective methods for solving the problem and necessary protection

Table of contents:

Buffer overflow: causes, effective methods for solving the problem and necessary protection
Buffer overflow: causes, effective methods for solving the problem and necessary protection

All programmers are aware of the potential threat of buffer overflows in their programs. There are many threats associated with it, both in new and old software, regardless of the number of patches made. Attackers can take advantage of this bug by injecting code specifically designed to overflow the initial part of the dataset and then write the rest to the memory address adjacent to the overflow.

The data may contain executable code that would allow attackers to run larger, more complex programs or give them access to the system. A bug is very hard to find and fix because the code is millions of lines long. The fixes for these bugs are quite complex and, in turn, are also error-prone, making the troubleshooting process more difficult.

Buffer overflow detection

Buffer Overflow Detection
Buffer Overflow Detection

Before lookingoverflow, you need to know what it is. As the name implies, these vulnerabilities are related to buffers or memory allocation in languages that provide direct low-level read and write access.

When using C and Assembler languages, reading or writing such allocations does not involve automatic bounds checking. Therefore, if a stack buffer overflow is detected in a given application, there is no check to see if the number of bytes can be placed in the buffer in question. In such cases, the program can "overflow" its capacity. This causes data written after padding to overwrite the contents of subsequent addresses on the stack and read additional ones. Overflow may occur unintentionally due to user error.

Sometimes it is caused by a malicious actor sending carefully crafted malicious input to a program that then tries to store it in an insufficient buffer. If this detects a stack buffer overflow in this application, the excess data is written to the adjacent one, where it overwrites any existing data.

They usually contain the return pointer of the exploited function - the address where the process should go next. An attacker can set the new values to point to an address of their choice. The attacker usually sets new values to indicate where the payload is located. This changes the execution path of the process and instantly transfers control to the malicious code.

Using a buffer overflow allowsan attacker to control or terminate a process, or change its internal variables. This violation ranks among the top 25 most dangerous programming errors in the world (2009 CWE/SANS Top 25 Most Dangerous Programming Errors) and is defined as CWE-120 in the system weakness enumeration dictionary. Although well studied, they continue to harm popular programs.

Simple buffer usage vector

When working with source code, you need to pay special attention to where buffers are used and modified. Of particular note are functions related to input provided by the user or another external source, as they provide a simple vector to use when a stack buffer overflow is detected. For example, when the user asks a "yes" or "no" question, it is useful to store the user's string data in a small buffer for the "yes" string, as shown in the following example.

Simple buffer usage vector
Simple buffer usage vector

Looking at the code, you can see that there is no bounds checking. If the user types "maybe", then the program will crash rather than prompt the user for a response, which is written to buffer regardless of its length. In this example, since user's answer is the only variable declared, the next values on the stack will be the return address value, or the memory location where the program will return after the ask Question function is executed.

This means that if the user enters four bytes of data, which is enough to overflow the command buffercustomer, a valid return address will follow, which will be changed. This will cause the program to exit the function at a different point in the code than originally intended and may cause the software to behave in dangerous and unintended ways.

If the first step to detect buffer overflows in source code is to understand how they work, the second step is to study external input and buffer manipulation, then the third step is to know which functions are affected by this vulnerability and which can act like red flags. The gets function is great for writing outside of the buffer provided to it. In fact, this quality extends to the entire family of related capabilities, including strcpy, strcmp, and printf/sprintf, wherever one of these overflow vulnerability functions is used.

Removal from codebase

If a stack buffer overflow is detected in the source code, a consistent deletion of them from the database will be required. To do this, you need to be familiar with safe working methods. The easiest way to prevent these vulnerabilities is to use a language that does not allow them. The C language has these vulnerabilities due to direct memory access and lack of strong object typing. Languages that do not share these aspects are usually immune. These are Java, Python and. NET, along with other languages and platforms that do not require special checks or modifications.

Of course, it is not always possible to completely change the development language. In this case, safe methods are used to deal with command buffer overflows. In the case of string manipulation functions, there has been a lot of discussion about which methods are available, which are safe to use, and which should be avoided. The strcpy and strcat functions copy a string to a buffer and append the contents of one to the other. These two methods exhibit unsafe behavior because they do not check the bounds of the target buffer, and write out of bounds if there are enough bytes to do so.

Alternative Defense

One of the often suggested alternatives is linked versions that write to the maximum target buffer size. At first glance, this looks like the perfect solution. Unfortunately, these functions have a small nuance that causes problems. When the limit is reached, if the terminating character does not fit in the last byte, severe buffer read failures occur.

Alternative defense
Alternative defense

This simplified example shows the danger of non-null strings. When foo is placed in the normal buffer, it is null-terminated because it has extra space. This is the best scenario. If the bytes in the buffer overflow on the stack are in another character buffer or another printable line, the print function continues reading until the terminating character of that line is reached.

The downside is that the C language does not provide a standard, safe alternative to these functions. Nevertheless, there is also a positive - the availability of several implementations for a specific platform. OpenBSD provides strlcpy and strlcat which work similar to the strn functions, except thatthat they truncate the string one character early to make room for the null terminator.

Similarly, Microsoft provides its own secure implementations of commonly used string processing functions: strcpy_s, strcat_s and sprintf_s.

Using the safer alternatives listed above is preferred. When this is not possible, perform manual bounds checking and null termination when processing string buffers.

Compilation vulnerabilities

Compilation vulnerabilities
Compilation vulnerabilities

If an unsafe function leaves open the possibility of a C buffer overflow, all is not lost. When a program is run, compilers often create random values, known as canaries, and push them onto the stack, so they are dangerous. Checking the canary's value against its original value can determine if a Windows buffer overflow has occurred. If the value has been changed, the program will exit or enter an error state rather than the potentially changed return address.

Some modern operating systems provide additional buffer overflow protection in the form of non-executable stacks and address space layout randomization (ASLR). Non-Executable Stacks - Data Execution Prevention (DEP) - Marks the stack, and in some cases other structures, as areas where code will not be executed. This means that an attacker cannot inject exploit code onto the stack and expect it to succeed.

Before fixing the buffer overflow,unpacked on ASLR PC. It was designed to protect against return-oriented programming as a workaround for non-executable stacks, where existing code snippets are chained together based on their address offset.

It works by randomizing the memory regions of structures so that their offsets are harder to determine. Had this protection been in place in the late 1980s, the Morris worm might have been prevented. This is because it functioned in part by filling a buffer in the UNIX finger protocol with the exploit code and then overflowing it to change the return address and point to the full buffer.

ASLR and DEP make it hard to know exactly what address to use by making that area of memory completely unusable. Sometimes a vulnerability slips through cracks that are open to a buffer overflow attack despite the presence of controls at the development, compiler, or operating system levels.

Static coverage analysis

There are two critical problems in the buffer overflow situation. First, you need to identify the vulnerability and change the code base to solve the problem. Second, they ensure that all versions of the buffer overflow vulnerability code are replaced. Ideally, this will start with an automatic update of all internet-connected systems.

This update cannot be assumed to provide sufficient coverage. Organizations or individuals may use the software on systems with limited internet access that require manual updates. This means that the news about the update should bedistributed to any administrators who may be using the software, and the patch should be readily available for download. Patch creation and distribution is carried out as close as possible to the discovery of the vulnerability, minimizing the time of the vulnerability.

By using safe buffer handling functions and appropriate compiler and operating system safety features, you can create strong protection against buffer overflows. With these steps in mind, consistently identifying flaws is a critical step in preventing an exploit.

Combining lines of source code looking for potential threats can be tedious. In addition, there is always the possibility that human eyes may miss something important. Static analysis tools are used for code quality assurance and were developed specifically to detect security vulnerabilities during development.

Static coverage analysis sets red flags for potential buffer overflows. Then they are processed and corrected separately so that they are not manually searched in the database. These tools, combined with regular checks and the knowledge of how to fix overflows, allow you to identify and fix the vast majority of bugs before software development is complete.

Performing a root attack

Encoding errors usually cause buffer overflows. Common application development mistakes that can lead to it include failing to allocate large enough buffers and not havingmechanism for checking these problems. Such errors are especially problematic in C/C++ languages, which do not have built-in overflow protection and are often the target of buffer overflow attacks.

In some cases, an attacker injects malicious code into memory that has been corrupted due to a stack buffer overflow. In other cases, they simply take advantage of neighboring memory corruption. For example, a program that asks for a user's password to grant him access to the system. In the code below, the correct password grants root privileges. If the password is incorrect, the program does not grant privileges to the user.

The program does not grant privileges to the user
The program does not grant privileges to the user

In the example above, the program grants the user root privileges even if the user entered the wrong password. In this case, the attacker provides an input that is longer than the buffer can hold, creating an overflow that overwrites the memory of the integer pass. Therefore, despite the wrong password, the value of pass becomes non-zero, and the attacker gains root rights.

Temporary storage attack

A buffer is a temporary area for storing data. When a program or system process allocates more data than was originally allocated for storage, the extras overflow. This causes some of them to leak into other buffers, corrupt or overwrite data.

In an overflow attack, the extra data contains special instructions for actions intendedhacker or malicious user, for example, they trigger a response that corrupts files, alters data, or exposes personal information.

An attacker uses an overflow exploit to take advantage of a program that is waiting for user input. There are two types of buffer overflow: stack-based and heap-based. Heap-based ones are difficult to implement and least common, but attack the application by filling up the space reserved for the program.

Stack is a memory space used to store user input. This overflow is more common in attackers using applications.

Modern compilers usually provide the ability to check for overflow at compile/link time, but it is quite difficult to check for this problem at runtime without some additional exception handling protection mechanism.

Performing an attack via root
Performing an attack via root

Program options:

  1. Input: 12345678 (8 bytes), program runs smoothly.
  2. Input: 123456789 (9 bytes), the message "Segmentation Fault" will appear, the program ends.

Vulnerability exists due to overflow if user input argv exceeds 8 bytes. For a 32-bit system (4 bytes) fill the memory with a double word (32 bits). The character size is 1 byte, so if you request a buffer with 5 bytes, the system will allocate 2 double words (8 bytes). This is why Buffer will overflow if more than 8 bytes are entered.

Similar standard functions that are technicallyless vulnerable, exist. For example, strncpy(), strncat() and memcpy(). The problem with these functions is that it is the responsibility of the programmer, not the compiler, to determine the size of the buffer.

Every C/C++ programmer should know the problem before coding. Many generated problems can be overflow protected in most cases.

Dangers in C/C++


Users of C should avoid using dangerous functions that don't check bounds unless they are sure the bounds won't be exceeded. Functions that should be avoided in most cases to ensure protection include the strcpy functions. They should be replaced with functions like strncpy. Use of the strlen function should be avoided if the user is sure that a terminating NIL character will be found. The scanf() family: scanf(3), fscanf(3), sscanf(3), vscanf(3), vsscanf(3), and vfscanf(3) are dangerous to use, and should not be used to send data to a string without controlling the maximum length, "format %s" is a particularly common failure.

Officially, snprintf() is not a standard C function in the ISO 1990 classification. These systems do not protect against buffer overflows, they just call sprintf directly. The current version of Linux snprintf is known to work correctly, that is, it actually respects the established boundary. The return value of snprintf() also changes.

Version 2 of the Unix Specification (SUS) andthe C99 standard differ in what snprintf() returns. Some versions of snprintf don't guarantee that the string will end in NIL, and if the string is too long it won't contain NIL at all. The glib library has g_snprintf() with serial return semantics, always ends with NIL, and most importantly, always respects the length of the buffer.

Communication port buffer overflow

Communication port buffer overflow
Communication port buffer overflow

Sometimes the serial port reports a buffer overflow. This problem can be caused by several factors. These include the speed of the computer, the baud rate of the data being used, the size of the FIFO of the serial port, and the size of the FIFO of the device that sends data to the serial port.

Flow control will wait until a certain number of bytes are in the buffer before the processor sends a message or signal to another device to stop transmitting. At higher baud rates, the serial port will receive several bytes from the time the buffer flow control level is reached and the device stops transmitting.

These extra bytes will be larger if a high priority process controls the target's processor in real time. Since the communication port buffer overflow process has a higher priority than the VISA interrupt, the processor will not take any action until such a one is completed in real time.

The default VISA and Windows settings for a 16-byte FIFO are 14 bytes,leaving 2 bytes in the FIFO when the device attempts to send a message from the source. At higher baud rates on slower computers, it is possible to receive more than 4 bytes when the serial port requests the processor by sending a signal to stop sending.

To solve the problem when a stack buffer overflow is detected in Windows 10, you need to open Device Manager. Then find the COM port for which the settings are being changed and open the properties. Next, click on the "Advanced" tab, a slider will appear that changes the size of the clipboard overflow so that the UART turns on flow control faster.

The default value is sufficient in most cases. However, if a buffer overflow error occurs, decrease the value. This will cause more interrupts to be sent to the processor with slow bytes in the UART.

Secure development practices

Secure Development Methods
Secure Development Methods

Secure development practices include regular testing to detect and fix overflows. The surest way to avoid or prevent it is to use automatic protection at the language level. Another fix is run-time bounds checking, which prevents overflow by automatically checking that the data written to the buffer is within valid bounds.

Veracode Cloud Service detects code vulnerabilities such as buffer overflows, so developers fix them before they are exploited. Industry-unique patented technologyBinary Static Application Security Testing (SAST) Veracode analyzes it, including open source and third-party components, without having to access it.

SAST complements developer threat modeling and code reviews by detecting errors and omissions in code faster and more cost-effectively through automation. It is typically launched early in the software development lifecycle because it is easier and cheaper to fix problems before going into production deployment.

SAST exposes critical vulnerabilities such as SQL Injection, Cross Site Scripting (XSS), Buffer Overflow Error, Unhandled Error Conditions, and potential nooks and crannies. In addition, SAST binary provides useful information that prioritizes severity and provides detailed remediation instructions.

The buffer overflow vulnerability has been around for nearly 3 decades, but it's still onerous. Hackers around the world continue to consider it their default tactic due to the sheer number of susceptible web applications. Developers and programmers are working hard to fight this evil of IT technologies, coming up with more and more new ways.

The main idea of the last approach is to implement a patching tool that makes multiple copies of the return addresses on the stack and then randomizes the location of all copies in addition to the number. All duplicates are updated and checked in parallel so that any discrepancy betweenthem indicates a possible attack attempt and throws an exception.

Popular topic

Editor's choice

  • What is a proxy server and what is it for?
    What is a proxy server and what is it for?

    The word "proxy" has ever been heard by any of us, but not everyone knows what a proxy server is and what its purpose is

  • Google Chrome not working. What to do?
    Google Chrome not working. What to do?

    So why doesn't Chrome launch when we click on its desktop icon? Google Chrome not working for several reasons

  • Recovery console. Main benefits of using
    Recovery console. Main benefits of using

    Computers are quite technically complex devices. In this regard, many users from time to time encounter failures in the operation of the operating system and other programs. In most cases, you can fix problems in a matter of minutes, especially if the computer technician has the necessary skills. If a critical failure occurs, it is recommended to use the recovery console

  • What is the cluster size?
    What is the cluster size?

    The space of any storage medium (hard drive or flash drive) is not a whole piece, but a system of memory cells called clusters

  • What is defragmentation and why is it needed?
    What is defragmentation and why is it needed?

    Modern users are often spoiled by powerful computers and inexpensive components to such an extent that they do not even know the basic concepts. That is why they often find themselves in a situation where the car begins to shamelessly “slow down” and respond with extreme reluctance to any commands. As a rule, “evil viruses” that have entered the computer are blamed for everything, but sometimes the reality turns out to be much more prosaic