Post

Uninitialized Data Access

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() calls scanf 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 local buf variable at the same address again.
  • vuln()’s buf therefore contains the bytes left by func()
  • vuln() calls system(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.

Start

Enter AAAABBBBCCCCDDDDD

No lets view it in memory

stack_frame1

We can see that our buffer starts at 0x7fffffffdeb0 in the stack frame of the func() function.

b 1

I set a breakpoint just after the buf was declared in the vuln() function so that we can view the stack frame from there.

stack frame2

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.
This post is licensed under CC BY 4.0 by the author.