This application will force two normal malloc(...)
calls to point to the same memory address.
In turn, both the pointer username
and command
will share the same value.
Due to this, any information entered as the username will then be executed by the system(...)
function.
This file displays how a simple logic error can potentially give RCE capabilities to an attacker.
In a more realistic scenario, this initial vulnerability would potentially lead to a buffer overflow, making the exploit more complicated then it is here, but still enabeling remote code execution or system crashes (DoS).
Below is a simplified version of how the vulnerability works.
When freeing a memory chunk, it gets added to a stack, which is later used to quickly
find memory chunks that can be allocated for other values.
If a chunk that was freed once is then freed again, it will be added to this stack a second time.
If the program now starts allocating new memory space, the same address can be received from
the stack twice by the malloc(...)
function.
After the first free(a);
the stack of freed addresses looks like this:
┌──────┌───┌──────┐
│ Head │ a │ Tail │
└──────└───└──────┘
If a
was freed the second time immediatley, this would cause a core dump on most systems.
Because of this, the pointer b
will be freeed in between.
┌──────┌───┌───┌──────┐
│ Head │ b │ a │ Tail │
└──────└───└───└──────┘
Now it is possible to free a
for the second time.
┌──────┌───┌───┌───┌──────┐
│ Head │ a │ b │ a │ Tail │
└──────└───└───└───└──────┘
Now, if the memory space is being allocated, the stack will be checked for free memory space.
The line char* command = malloc(50);
will assing the address of a
to command
.
┌──────┌───┌───┌──────┐
│ Head │ b │ a │ Tail │ -> a is no longer part of the stack.
└──────└───└───└──────┘
The pointer some_pointer
is used to allocate space pointed at by b
and to remove it from the stack.
┌──────┌───┌──────┐
│ Head │ a │ Tail │ -> b is no longer part of the stack.
└──────└───└──────┘
Last, username
is allocated and assigned the address space at a
again.
┌──────┌──────┐
│ Head │ Tail │ -> the stack is now empty.
└──────└──────┘
Because of this, both the pointer command
and username
now point to the same location.
In most cases, this will simply lead to memory corruption and in turn crash the application.
However, if one of the pointer values can be controlled by an attacker (e.g. through an input
field in an exposed web service) and the other pointer is used in an insecure manner (e.g. interacts with strcpy(...)
, ...), the vulnerability may lead to a bufferoverflow attack and provide an attacker with remote code execution or privilege escalation capabilities.
The file can be compiled with:
gcc -o poc poc.c
The file can then be run with:
./poc
Simply enter a bash command as your username and watch the magic happen.
This work is partially based on the following article: https://heap-exploitation.dhavalkapil.com/attacks/double_free