Lecture Notes
This lecture will present an overview over issues involving concurrency between applications using shared resources.
Download here
Relevant files
Practical tasks
An example of the TOCTOU
vulnerability can be found in the next snippet.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char** argv){
if(argc != 2) {
printf("Usage: %s file\n", argv[0])
-
return -1
-
}
char *fn = argv[1]
-
if(!access(fn, R_OK)) {
printf("Showing the contents of %s\n",fn)
-
char* buffer = malloc(1024)
-
memset(buffer, 0, 1024)
-
FILE* fp = fopen(fn, "r")
-
while(1) {
int r = fread(buffer, 1, 1024, fp)
-
fwrite(buffer, 1, r, stdout)
-
if(r <= 0)
break
-
}
fclose(fp)
-
free(buffer)
-
} else
printf("Permission denied\n")
-
return 0
-
}
The code is vulnerable because the access
function, determining that the Real user (by its real user id) can access the file, is done before the actual read.
There is a window of opportunity between the access
and fopen
, where the file can be replaced.
Compile and prepare the file using:
gcc -o cat cat.c
sudo chown root cat
sudo chmod u+s cat
This sets the SET-UID
bit, which will make the file execute with Effective User ID of 0
(root
). However, the access
function considers the Real User ID, not granting users with files that they should not have had access to.
You can try to use the file to read /etc/passwd
and /etc/shadow
. The second will fail as expected due to invalid permissions.
You can test the file with:
./cat /etc/passwd
But the nice thing would be to use the file to access /etc/passwd
.
Task:
- Plan an attack to this binary allowing it to read
/etc/shadow
or any other priviledged file.