Race conditions have caused quite a few issues and privilege escalation attacks on the Android platform; many of them allowing malicious attackers to gain root privileges.
Essentially, race conditions are caused by the lack of enforced mutual exclusion when a process on a multithreaded (a platform where more than one process is allowed to run concurrently) system that uses preemptive process scheduling. Preemptive scheduling allows a task scheduler to interrupt a thread or running process preemptively, meaning without first waiting for the task to be ready for interruption. This enables race conditions because often developers don't enable applications to operate in a way that accommodates arbitrary and unpredictable interrupts from the process scheduler; as a result, processes that rely on access to potentially shared resources like files, environment variables, or data structures in shared memory are always "racing" to get first and exclusive access to these resources. Attackers abuse this situation by gaining access to these resources first and corrupting them in a way that enables either damage to the processes operation or allows them to maliciously influence the process's behavior. A simple example would be a program that checks if a user authenticating themselves is in a given file listing the valid usernames; should this process not accommodate the preemptive scheduler, it may only access the file after a malicious user has corrupted it by adding his/her username to the list, allowing them to be authenticated.
In this walkthrough, I will detail some basic race condition vulnerabilities and discuss other potential causes; I will also detail exploitation of a few of the most basic race condition vulnerabilities. The walkthrough ends with references and useful sources of information on past Android-based race condition vulnerabilities; most of them reported in the year of this writing.
Exploitation of race condition vulnerabilities depends on a few factors, namely an attacker must at least be able to:
Taking these conditions into account, let's look at some constructed examples of race condition vulnerabilities and how to exploit them on Android.
Before we start exploiting race conditions, we need to prepare an example. Here's how you do that:
#include <stdio.h> #include <unistd.h> #include <errno.h> #define MAX_COMMANDSIZE 100 int main(int argc,char *argv[],char **envp){ char opt_buf[MAX_COMMANDSIZE]; char *args[2]; args[0] = opt_buf; args[1] = NULL; int opt_int; const char *command_filename = "/data/race-condition/commands.txt"; FILE *command_file; printf("option: "); opt_int = atoi(gets(opt_buf)); printf("[*] option %d selected... ",opt_int); if (access(command_filename,R_OK|F_OK) == 0){ printf("[*] access okay... "); command_file = fopen(command_filename,"r"); for (;opt_int>0;opt_int--){ fscanf(command_file,"%s",opt_buf); } printf("[*] executing [%s]... ",opt_buf); fclose(command_file); } else{ printf("[x] access not granted... "); } int ret = execve(args[0],&args,(char **)NULL); if (ret != NULL){ perror("[x] execve"); } return 0; }
Compile this by following the same process as detailed in the Cross-compiling native executables recipe and deploy it to your Android device. Try deploying it to a partition or folder that's been mounted as executable and readable by any user on the Android system (to see how to do this, please refer to the Copying files off/into an AVD recipe in Chapter 1, Android Development Tools). Throughout this recipe, we use the partition mounted as /system
, which was remounted with read and write permissions, as in other recipes. Please note this may cause the NDK to throw out a couple of warnings, but as long as everything compiles to an executable, you're good to go!
commands.txt
file in the directory mentioned in the code, namely /data/race-condition/command.txt
. This requires making a race condition folder in the /data
path. A good example of how to do this can be found in the Inspecting network traffic recipe in Chapter 4, Exploiting Applications, since we needed to create a similar setup for TCPdump
.setuid
permission for this executable on the Android device; you can do this by executing the following command after deploying it to the device:chmod 4711 /system/bin/race-condition
This command also makes sure any user on the system has execute permissions. Please be aware that you will need root permissions to perform this command. We are simulating the effect of a setuid
binary and how it can cause arbitrary code execution.
We have everything set up for exploitation; we can move onto detailing this exploitation now.
To exploit the vulnerable binary, you will need to do the following:
su
to assume another application's access rights.Try accessing some root-owned folders and files that don't have execute, read, or write permission set for your user. Here I've chosen user 10170
as an example, and you should see the Permission denied
messages being thrown around when you try to access the /cache/
directory:
race-condition
binary. We do this by augmenting the commands.txt
file with another command, namely /system/bin/sh
, which will open a shell for us. You can do this by executing the following command:echo "/system/bin/sh" >> /data/race-condition/commands.txt
The /system/bin/sh
command should now be the last entry in the commands.txt
file, this means, if we hope to select it from the menu we need to choose option 5.
race-condition
on the Android device and supply 5
as an option. The vulnerable binary would then execute the sh
command and give you root permissions./cache
. If you're running a Jelly Bean or later version of Android, you should not see any Permission denial
messages, which means you've just escalated your privileges to root!The preceding example is designed to detail the most basic concepts in race conditions, namely when an application accesses a file that any other process can augment and uses it to perform actions as the root user. There are more intricate and subtle situations that cause race conditions, one that's been commonly exploited are those involving symbolic links. These vulnerabilities stem from an application's inability to discern a file from a symbolic link, which allows attacks to augment files via a crafted symbolic link or when a file reads a symbolic or hard link but is incapable of determining the authenticity of the link target, which means the link can be redirected maliciously. For more modern examples of race condition vulnerabilities, check out the links in the See also section.
3.147.48.78