Uninitialized Data Access
Overview
So what are Uninitialized variables? Uninitialized variables are variables that are declared byt they are not assigned a value
e.g.
1
2
3
4
5
6
7
8
9
#include <stdio.h>
// complile : gcc vuln.c -o vuln
int main() {
int a, b;
printf("a = %d, b = %d\n", a, b);
return 0;
}
Output
1
2
./vuln
a = 32676, b = -1360491824
The values are random numbers which we did not assign. Since we did not initialize any value tot the variables, they will contain unpredictable or garbage values, which are values left in memory at that particular location.
So how is this a vulnerability?
Not all uninitialized variables are security vulnerabilities, but there are cases where they are. They become security vulnerabilities when leftover (previous) values in memory from previous program executions or other parts of the program that are attacker controlled input data.
Uninitialized data access can lead to these vulnerabilities:
- Information Disclosure: The uninitialized variable can contain information about the program’s memory layout or internal states, addresses in the stack, which might be used to craft an exploit.
- Arbitrary Code Execution: An attacker may be able to manipulate uninitialized variables in such a way that they can control the program’s execution flow which can lead to arbitrary code execution.
Examples
Stack
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func() {
char buf[32];
printf("Enter a str: ");
scanf("%31s", buf);
}
void vuln() {
char buf[32];
system(buf);
}
int main() {
func();
vuln();
return 0;
}
Compile
1
gcc -o vuln2 ./vuln2.c
when i run it and enter the string: “/bin/sh”
1
2
3
4
./vuln2
Enter a str: /bin/sh
$ whoami
hacker
Why am i getting a shell?
Now i entered ‘ls -lha’
1
2
3
4
./vuln2
Enter a str: ls -lha
chall flag.txt vuln vuln2.c
chall.c notflag.txt vuln2 vuln.c
What actually happens.
func()
callsscanf
and writes your input into a local stack slot.func()
returns. The contents at the stack address are not cleared.vuln()
is called. Its stack frame happens to allocate its localbuf
variable at the same address again.vuln()
’sbuf
therefore contains the bytes left byfunc()
vuln()
callssystem(buf)
.
Why is the program executing the string that i entered? when that buffer is in another function?
Lets find out.
In gdb
set breakpoints at the beginning and at the end of the vuln()
and func()
functions.
Enter AAAABBBBCCCCDDDDD
No lets view it in memory
We can see that our buffer starts at 0x7fffffffdeb0
in the stack frame of the func()
function.
I set a breakpoint just after the buf
was declared in the vuln()
function so that we can view the stack frame from there.
We can see that our buffer also starts at 0x7fffffffdeb0
in this stack frame and also that the data from the stack frame from func()
is still present in the stack frame from vuln()
. So the contents of the first stack frame from func()
where not cleared when func()
returned, then the stack frame of vuln()
allocated the buf
address at the same address as the previous stack frame, which is then passed as a command to system()
.
Heap
Common Causes
- Not initializing local variables or heap data at declaration time.
- Only partially initializing structs and objects
- Accidental failure to initialize down an uncommon control flow path.
- e.g. passing a pointer to an uninitialized struct to a function and expecting it to perform initialization, but then it returns early before any initialization actually occurs.