On Thu, Nov 14, 2013 at 7:44 AM, Gleb O. Raiko <raiko@xxxxxxxxxxxx> 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/