Quantcast
Channel: C/C++ – PRDeving
Viewing all articles
Browse latest Browse all 11

What is Buffer Overflow vulnerability and how do we exploit it.

$
0
0

Buffer overflow is probably the most feared security hole in software since it’s not just a development issue (it is) but also a language standard library “error”. This makes buffer overflow vulnerabilities hard to spot and fix and ridicously powerfull.
But, what is a buffer overflow vulnerabilty and how do we exploit it?Imágenes integradas 1

What is a buffer?

A buffer is a stack or contiguous block of computer memory that holds multiple elements of the same data type, so, when we define an array we are setting a buffer of, for example 8 char elements, or, in i386 architectures, 8 bytes:

char buf[8];

This memory space can now store 8 char elements or bytes (in this case).

Writting to the buffer

When we store data in that buffer we are writing between the outbounds of that buffer, so, if we fetch the data from buf we will have the blocks from buff to buf + (7 * 8), where buf is the first block.

What is a buffer overflow?

To overflow a buffer is to write over the limits of it. If we try to store 9 bytes in the buf variable, we’ll pass the bounds of the array getting a buffer overflow since the input exceeds the buffer capacity, writing in the contiguous memory blocks. In interpreted languages such as JS or Python, this could be harmless but in languages like C or C++,  this extra byte will be written in the 9th position of the array, and, since there’s no such position, it’ll overwrite a wrong memory block, leading to corrupt memory.

Let’s say we have this stack

1. buff[0]
2. buff[1]
3. buff[2]
4. buff[3]
5. buff[4]
6. buff[5]
7. buff[6]
8. buff[7]
9. importantVariable

if we set 9 bytes instead of 8, the 9th will overwrite “importantVariable”, this could (potentially) result either in a broken flow and unexpected failure or in an arbitrary code execution, shell spawn or priviledge escalation.

Exploiting Buffer Overflow

Now let’s code the example above, let’s write a simple login where no one but the admin can access the admin panel:

#include <stdio.h>
#include <string.h>

int main() {
char buff[10];
int userID;

printf("Enter the password: ");
scanf("%s", buff);

if (strcmp(buff, "admin") == 0) userID = 1;

if (userID) {
printf("\nWelcome admin\n");
}

return 0;
}

If we compile this code and run it, we can see that, if the password provided is “admin”, the userID variable will be set on and the administration panel can be accesed, but if it is not, the program ends.

But, what if we overflow the password buffer? we know that the password buffer length is 10 bytes, and, right after this, there’s the userID variable, we have to set something on it to enter the control panel, so let’s use “0123456789abc” as password, the buffer overflows on “9” ovrewriting the userId that has value now, going smoothly throught “if (userID)” and getting admin priviledges.

But why? to understand it is important to notice how the stack and the memory works.
In a computer, when variables are initialized they are pushed into a pile called stack, and, when they are needed, they are popped from it.
But only whole “words” can be stored in the stack, in intel x86 architectures a word is formed by 4 bytes, so, in order to store our 10 bytes buffer, the OS will assign it 12 bytes of memory instead (3 words), and, of course, userID will be stored as 1 word too (4 more bytes), so we will have 16 bytes of data in the stack.

But x86 CPU’s are something called little-endian, this means that the data is pushed into the stack in byte pairs starting from the last (low) byte, the result of our custom input word-fit would be something like:

BUFFER ->   1   2   3   4   5   6   7   8   9   0   a   b   c
MEMMO -> 9078 5634 1200 bc0a

Where the expected memory structure would be:

MEMMO -> 00BB BBBB BBBB 0U00
(Being “B” a buffer byte and “U” the userId byte)

As you can see, what we are doing here is to overflow the buffer until we can write in the userID memory block, exactly 15 bytes from the buffer base.
Since there’s place just for 10 elements, the “ab” overflows the two free bytes of the buffer last word (from 10th to 12th bytes) and the “c” overflows the userID variable.

Try it!!
Now, we have admin priviledges, cool, isn’t it?

We are overwriting the memory so we could jump to our custom code (injecting libraries or raw machine code), or cause failures in the software, this advanced exploting techniques will be covered in other posts.

How to fix Buffer Overflow

First of all, sanitize input and control data length.
In this case, instead of using scanf, we’d use read, so we can control how many bytes we want to read.

read(STDIN_FILENO, buff, 10);

Also, instead of using strcmp, we’d use strncmp, forcing the program to compare just 10 bytes.

But remember, there’s no invulnerable software, code must be audited and tested, and even after that, applications that depends on third party libraries or dynamic input are error prone.

Hope it helped 🙂


Viewing all articles
Browse latest Browse all 11