An Introduction To Exploit Development: BOF part 1
What is an exploit?
An exploit is often refered to as code designed to take advantage of a vulnerabity.
In example, when a new vulnerability is presented by a researcher it is often accompanied by a proof-of-concept (POC), an exploit could be the weaponization of this research.
Exploits are attractive means of gaining intial access and/or privilege escalation. A good example of this is Eternalblue, this exploit was developed by the National Security Agency (NSA) and leaked by the Shadow Brokers on April 14, 2007.
Read the book Sandworm (or listen) for an insight into cyberwarfare and the use of exploits.
Common vulnerability classes
- Buffer Overflow (BOF)
- Use-After-Free
- Out-Of-Bounds Memory Disclosure
- Arbitrary Write
We are going to focus on learning the basics of the Buffer Overflow vulnerabilitiy.
Buffer Overflow
A buffer overflow occurs when the size of a buffer is calculated incorrectly, allowing more data than planned to be written to the destination buffer.
So what is a buffer?
A buffer is temporary storage present in memory used to hold data. for the sake of learning it is irrelevant at the moment wether it is held on the stack or heap.
In C, a char
data type occupies 1 byte of memory. Therefore, the array char a[5]
would occupy a total of 5 bytes of memory, with each element of the array occupying 1 byte.
The diagram below depicts a visualization of 5 bytes stored in memory.
Exploitation process example:buf2
buffer was filled with more data than expected, and the buf1
buffer was therefore overwritten with data supplied by the attacker to buf2
. The attacker also managed to overwrite the instruction pointer which stores the return address. Thus, the attacker can now choose which memory address is returned by the calling function.
Leading to the attacker having full control of what code is to be executed.
If you have never heard of the instruction pointer (EIP) and frame pointer (EBP) they are in simple terms used to manage the flow of execution in a program, and to keep track of the current position and context of the program as it executes.
Overflows of the stack (Stack overflow) or the heap (Heap overflow) are examples of buffer overflows. To avoid confusion, we don't make a distinction between these two in this introduction.
Through out this article we will be conducting our example in the C language. C is perfect for learning about buffer overflows as the C and C++ languages provide no automatic bounds checking, making them susceptable to BOF's. It is simply up to the programmer to perform bounds checking for every variable read into the program.
Analyzing vulnerable source code:
This very simple application presented from an owasp example that reads from the standard input of an array of the characters, and copies it into the buffer of the char type. The size of this buffer is eight characters. After that, the contents of the buffer is displayed and the application exits.
In this code, the buffer buf
has a fixed size of 8 bytes. If a user inputs a string larger than 8 bytes, gets()
will write the extra bytes beyond the end of the buf
, which can overwrite other variables on the stack. This can result in unexpected program behavior, including crashes, security vulnerabilities, and even remote code execution, if an attacker can craft input to inject executable code into the overwritten variables.
Compilation:
gcc bof_1.c -o bof1
We can clearly see that the compiler is prompting us that the usage of "gets" is dangerous, and suggests the usage of fgets instead. This is due to the native C function "gets" not doing appropirate buffer length checks while fgets is the safe equivelent.
We can also utilize flawfinder to identify vulnerable statements in the C code.
Overflowing:
In the C code provided, the buffer size is declared as 8 bytes.
If you input more characters than the buffer size, the extra characters will be written to adjacent memory locations, which may contain other variables or even the program's return address. which if the input is long enough should overwrite the instruction pointer (EIP) and cause a crash due to the instruction pointer holding the memory address of the next instruction to be executed
Congratulations! you have just overflown your first buffer and crashed the program! 😎
Prevention:
To prevent a buffer overflow in this code, the gets()
function should be replaced with a safer function such as fgets()
, which limits the number of characters read into the buffer and ensures that the buffer is not overflowed.
Try this yourself and observe the result!
Some unsafe C functions and their safe equivelent:
- gets() --> fgets()
- strcpy() --> strncpy()
- strcat() --> strncat()
- sprintf() --> snprintf()
Real World Application
For real world application we are going to target "Seattle Lab Mail version 5.5" which has a previously disclosed buffer overflow vulnerability (https://www.exploit-db.com/raw/638) with the end goal of creating a custom exploit that we can use on our engagements!
But this will be done in the next blog post! so stay tuned and dont forget to subscribe to be notified.
If you identify any errors I greatly appreciate a comment or an email describing the mistake so that I can fix it.
Refrences:
Foster, J.C. (2005) “Writing Exploits II,” in Sockets, Shellcode, Porting & Coding: Reverse Engineering Exploits and Tool Coding for Security Professionals. Rockland, MA: Syngress Publishing, pp. 444–449.
Buffer overflow attack (no date) Buffer Overflow Attack | OWASP Foundation. Available at: https://owasp.org/www-community/attacks/Buffer_overflow_attack (Accessed: October 24, 2022).
Member discussion