Buffer Overflow Attacks and Defenses: Defensive Strategies to Deal with Digital Threats
Computers and digital technologies have become an essential part of modern life. However, with the development of this digital world, cyber security threats are also rapidly increasing. Among these threats are “Buffer Overflow” attacks, a type of attack that should be taken into consideration, especially from a software security perspective.
Buffer Overflow attacks allow malicious actors or attackers to exploit the system by overflowing memory in software. This can lead to serious security vulnerabilities and lead to the disclosure of sensitive information or the seizure of control of the target system.
In this article, we will examine what Buffer Overflow attacks are, how they work, and how to develop defenses against such attacks. Let’s start..
A buffer overflow is a security vulnerability that occurs when you write more data to an array then its capacity causing data to be written outside the array. The reason that these overflows are so dangerous is that this overflow data we can see here actually corrupts other import data. For example if you have an array of five numbers put 6 number in there or put 10 number.
Why do buffer overflows happen?
Buffer overflows occur due to programming errors or vulnerabilities in the software. These occur when data is written to a buffer, a temporary storage area in a computer’s memory, due to failure to check proper boundaries.
What’s the solution to buffer overflows. The solution is known as runtime bounds checking with the runtime bounce, checking every time we want to add a number to our array.
Runtime bound checking varies depending on how programming languages translate binary code.
Interpreter languages are translated into runtime by an interpreter so the code can be corrected and modified. It is impossible to see buffer overflow in these languages. We can give Python and Java as examples of this.
The code running in compiler time is first converted into executable binary codes. These binary codes are created once and compiled at any time. C and C++ are examples of this language. In this topic, we will talk about the vulnerability to buffer overflows of these languages.
How to Prevent Buffer Overflows?
Let’s examine the types of defense we mentioned in this table.
- ASLR
ASLR (Address Space Random Positioning) is a technique used in the field of computer security. ASLR is a security mechanism designed to prevent memory attacks and reduce the impact of malicious software that targets the operating system by force. ASLR protects against memory attacks by randomly locating memory regions of the operating system and application software.
Here’s how it works.
ASLR randomly positions memory regions used by the operating system and application software. This makes it difficult for a malicious attacker to guess the location of memory regions on the target system. A process that wishes to take advantage of ASLR, needs to use an operating system that supports it.
The power of ASLR depends on the level of randomness in the target system. For example, when an attacker tries to guess the address of a function on a target system, if that address contains only one random bit, the chance of success will be 50%. However, if this address contains four random bits, the chance of success will increase to 93.75%. If the address contains exactly one byte of randomness, the chance of success is only 1/256, and an attacker would need approximately 600 attempts to increase the success rate above 90%. That is, the more randomness there is, the less likely the attacker will succeed and the more difficult the attack becomes.
2. DEP
DEP(Data Execution Prevention) protects your computer by monitoring whether your programs are using system memory safely. It is a measure that ensures that the data segment on the CPU is set to be non-executable. It prevents code from executing in a memory region unless specifically specified by the kernel. In particular, for DEP to work, the processor must have NX (No-Execute) or XD (Execute Disable) features.
3. Use Safer Methods
It is important to prefer safer alternatives for critical functions. For example, using `strncpy()` instead of strcpy() prevents unexpected overflows of strings. Using fgets() instead of gets() allows you to read the data more safely. Such safe functions provide defense against overflow attacks.
//Unsafe Function Example (strcpy):
#include <stdio.h>
#include <string.h>
int main() {
char dest[5];
char source[] = "Betul Karaman";
strcpy(dest, source); //strcpy() function may exceed target array size.
printf("Full Name: %s\n", dest);
return 0;
}
//Safe Function Example (strcpy):
#include <stdio.h>
#include <string.h>
int main() {
char dest[5];
char source[] = "Betul Karaman";
strncpy(dest, source, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0'; //last item
printf("Full Name: %s\n", dest);
return 0;
}
4. Bound Checking
Programs often use index values when accessing data structures such as arrays. However, if index values are not properly controlled, vulnerabilities such as buffer overflow and other incorrect memory accesses can occur. For this reason, software developers perform bound checking when accessing arrays. This involves checking whether the index values are within the size or bounds of the array. For example, if the index value exceeds the boundaries of the array, this type of incorrect access is detected. Bound checking is built into many programming languages and environmental libraries.
5. Stack Canaries
Stack Canaries seem like a clear cut way to mitigate any stack smashing as it is fairly impossible to just guess a random 64-bit value. However bruteforcing the canary is method which would allow us to get through the canary check.
So how does this method work?
When the operating system creates the stack frame of each function call, it appends a random value to the end of this frame. This random value is called “canary”.
While the function is running, the canary value is not changed.
When the function terminates and the stack frame is closed, the canary value is checked. If the canary value has been changed, this may have occurred as a result of overflow or other faulty memory operations and may indicate a security vulnerability.
Stack canaries as a collaboration between the kernel, the
compiler and the C library. The workflow is as follows:
1. During each execve(), the kernel places a random value in the stack of
the new virtual memory.
2. The C runtime initialization functions that come with the GNU libc use
this value to compute the canary and place it in a well known location in
the process’s memory.
3. The entry generated by GCC takes this global “canary” value and places it on the stack. The end part of the function checks for incompatibility between local “canary” and global “canary” and terminates the process if they are different.
Buffer overflow is a vulnerability that poses a serious threat to computer security and still poses a major challenge to software and systems. Such vulnerabilities allow attackers to gain control and carry out malicious actions. Therefore, the prevention and detection of buffer overflow should be a high priority in secure software development processes and security practices.
See you in other articles! Good coding..