Bugtraq mailing list archives
Re: Superuser unsanitized environment vulnerability on Android <= 4.2.x
From: Kevin Cernekee <cernekee () gmail com>
Date: Thu, 14 Nov 2013 12:19:22 -0800
On Thu, Nov 14, 2013 at 7:44 AM, Gleb O. Raiko <raiko () niisi msk ru> wrote:
Considering ChainsDD Superuser you mentioned. Unfortunately, your mail describes just potential attack vectors. While I can't say for sure, Superuser isn't vulnerable at all, I'd like to note that su invokes the am script in the process with the credentials of the caller, not root. Thus, by manipulating the environment variables, file descriptors, signals, etc, the user can get yet another process with the same credentials, perhaps, with a shell or with an instance of Davlik VM inside.
Full disclosure: my testing so far has been mainly focused on SuperSU and CWM Superuser on JB 4.2/4.3, mostly due to (perceived?) Superuser market share and the fact that the respective developers responded to my initial problem report. I did not hear back from ChainsDD at all, and AFAICT the project is abandoned. From what I've been able to piece together, it looks like CM/AOKP users (~11-14 million[1][2]) are using the builtin CWM Superuser, and most other active modders (~20 million) are using SuperSU. Actual exploits were verified against these two projects. But you brought up an interesting question, so let's take a look. The easiest case to consider is JB 4.2: due to the new multiuser features, "am broadcast" requires a special system permission[3] and responds with this (not entirely accurate) message when run from e.g. UID 10003: W/ActivityManager( 413): Permission Denial: broadcast asks to run as user -1 but is calling from user 0; this requires android.permission.INTERACT_ACROSS_USERS_FULL or android.permission.INTERACT_ACROSS_USERS This is why CWM Superuser and SuperSU both execute am as root. For the pre-JB-4.2 case, ChainsDD Superuser does drop privilege before running am. Some random observations: - su will block for a little while waiting to hear back from the Java app, making it easy for us to hijack the sequence at just the right time - We have control over the parent's file descriptor for the socket which the app uses to convey the verdict: 27495 unlink("/dev/com.noshufou.android.su/.socket27495") = -1 ENOENT (No such file or directory) 27495 bind(12, {sa_family=AF_UNIX, path="/dev/com.noshufou.android.su/.socket27495"}, 110) = 0 27495 listen(12, 1) = 0 [...] 27495 getgid32() = 10003 27495 setresgid32(0xffffffff, 0x2713, 0xffffffff) = 0 27495 getuid32() = 10003 27495 open("/acct/uid/10003/tasks", O_RDWR|O_CREAT, 0666) = -1 EACCES (Permission denied) 27495 mkdir("/acct/uid/10003", 0775) = -1 EEXIST (File exists) 27495 setresuid32(0xffffffff, 0x2713, 0xffffffff) = 0 27495 sigprocmask(SIG_BLOCK, [CHLD], []) = 0 27495 vfork() = 27496 [...] 27496 execve("/system/bin/sh", ["sh", "-c", "/system/bin/am broadcast -a 'com.noshufou.android.su.REQUEST' --es socket '/dev/com.noshufou.android.su/.socket27495' --ei caller_uid '10003' --ei allow '-1' --ei version_code '17' > /dev/null"], [/* 23 vars */]) = 0 - Not sure if I have up-to-date source code for this binary, but I've seen at least one copy of activity.c that doesn't check the return values from setresuid(), possibly leaving it open to a rageagainstthecage-style attack[4] - Perms on /dev/com.noshufou.android.su are 0750, with Superuser's uid/gid - Superuser 3.2-RC3 has the android:debuggable flag set in the manifest, so the shell user might be able to use run-as to hijack its UID (3.1.3 doesn't) - The socket has a highly predictable filename - We have access to the intent's extra data from "su", and can manipulate it as desired - The caller's UID is "usually" passed over the socket by trusted code, but if you specify a version_code <= 15, SuRequestActivity.java will trust the data provided on the command line. This allows you to spoof a request from any installed app, or even the Android System So maybe try something like: BOOTCLASSPATH= su -c id & ps | grep su # note the PID and substitute below /system/bin/am broadcast -a 'com.noshufou.android.su.REQUEST' --es socket '/dev/com.noshufou.android.su/.socket27495' --ei caller_uid '1000' --ei allow '-1' --ei version_code '15' There is a bit of a social engineering component to this, so a malware app would probably want to recognize the UIDs of well-known root packages in order to maximize the odds that the user will approve the request. Can you think of a way to exploit ChainsDD Superuser without user interaction on pre-4.2 devices? [1] http://stats.cyanogenmod.com/ [2] http://stats.aokp.co/ [3] http://insitusec.blogspot.com/2013/02/interact-across-users-permission-side.html [4] http://dtors.org/2010/08/25/reversing-latest-exploid-release/
Current thread:
- Superuser unsanitized environment vulnerability on Android <= 4.2.x Kevin Cernekee (Nov 13)
- Re: Superuser unsanitized environment vulnerability on Android <= 4.2.x Gleb O. Raiko (Nov 14)
- Re: Superuser unsanitized environment vulnerability on Android <= 4.2.x Kevin Cernekee (Nov 14)
- Re: Superuser unsanitized environment vulnerability on Android <= 4.2.x Gleb O. Raiko (Nov 14)