timwr / CVE-2016-5195

CVE-2016-5195 (dirtycow/dirtyc0w) proof of concept for Android
941 stars 392 forks source link

How do you spawn a shell after exploit? #9

Closed naikel closed 6 years ago

naikel commented 7 years ago

I've tried execpl, system, even executing chmod(const char *pathname, mode_t mode) in the code but nothing seems to work.

I do get getuid() == 0, but I can't do anything with that privilege.

EDIT: My device does NOT have /system/bin/run-as with setuid and I have seen NO device that has it set.

turnerrocks1 commented 7 years ago

have a look at this "On some of the Linux distribution SELinux is enabled by default, which may cause some unwanted issues, if you don’t understand how SELinux works and the fundamental details on how to configure it. I strongly recommend that you understand SELinux and implement it on your environment. But, until you understand the implementation details of SELinux you may want to disable it to avoid some unnecessary issues.

To disable SELinux you can use any one of the 4 different methods mentioned in this article.

The SELinux will enforce security policies including the mandatory access controls defined by the US Department of Defence using the Linux Security Module (LSM) defined in the Linux Kernel. Every files and process in the system will be tagged with specific labels that will be used by the SELinux. You can use ls -Z and view those labels as shown below.

ls -Z /etc/

-rw-r--r-- root root system_u:object_r:etc_t:s0 a2ps.cfg -rw-r--r-- root root system_u:object_r:adjtime_t:s0 adjtime -rw-r--r-- root root system_u:object_r:etc_aliases_t:s0 aliases drwxr-x--- root root system_u:object_r:auditd_etc_t:s0 audit drwxr-xr-x root root system_u:object_r:etc_runtime_t:s0 blkid drwxr-xr-x root root system_u:object_r:bluetooth_conf_t:s0 bluetooth drwx------ root root system_u:object_r:system_cron_spool_t:s0 cron.d -rw-rw-r-- root disk system_u:object_r:amanda_dumpdates_t:s0 dumpdates

Method 1: Disable SELinux Temporarily

To disable SELinux temporarily you have to modify the /selinux/enforce file as shown below. Please note that this setting will be gone after the reboot of the system.

cat /selinux/enforce

1

echo 0 > /selinux/enforce

cat /selinux/enforce

0

You can also use setenforce command as shown below to disable SELinux. Possible parameters to setenforce commands are: Enforcing , Permissive, 1 (enable) or 0 (disable).

setenforce 0

Method 2: Disable SELinux Permanently

To disable the SELinux permanently, modify the /etc/selinux/config and set the SELINUX=disabled as shown below. One you make any changes to the /etc/selinux/config, reboot the server for the changes to be considered.

cat /etc/selinux/config

SELINUX=disabled SELINUXTYPE=targeted SETLOCALDEFS=0

Following are the possible values for the SELINUX variable in the /etc/selinux/config file

enforcing – The Security Policy is always Encoforced
permissive – This just simulates the enforcing policy by only printing warning messages and not really enforcing the SELinux. This is good to first see how SELinux works and later figure out what policies should be enforced.
disabled – Completely disable SELinux

Following are the possible values for SELINUXTYPE variable in the /etc/selinux/config file. This indicates the type of policies that can be used for the SELinux.

targeted – This policy will protected only specific targeted network daemons.
strict – This is for maximum SELinux protection.

Method 3: Disable SELinux from the Grub Boot Loader

If you can’t locate /etc/selinux/config file on your system, you can pass disable SELinux by passing it as parameter to the Grub Boot Loader as shown below.

cat /boot/grub/grub.conf

default=0 timeout=5 splashimage=(hd0,0)/boot/grub/splash.xpm.gz hiddenmenu title Enterprise Linux Enterprise Linux Server (2.6.18-92.el5PAE) root (hd0,0) kernel /boot/vmlinuz-2.6.18-92.el5PAE ro root=LABEL=/ rhgb quiet selinux=0 initrd /boot/initrd-2.6.18-92.el5PAE.img title Enterprise Linux Enterprise Linux Server (2.6.18-92.el5) root (hd0,0) kernel /boot/vmlinuz-2.6.18-92.el5 ro root=LABEL=/ rhgb quiet selinux=0 initrd /boot/initrd-2.6.18-92.el5.img

Method 4: Disable Only a Specific Service in SELinux – HTTP/Apache

If you are not interested in disability the whole SELinux, you can also disable SELinux only for a specific service. For example, do disable SELinux for HTTP/Apache service, modify the httpd_disable_trans variable in the /etc/selinux/targeted/booleans file.

Set the httpd_disable_trans variable to 1 as shown below.

grep httpd /etc/selinux/targeted/booleans

httpd_builtin_scripting=1 httpd_disable_trans=1 httpd_enable_cgi=1 httpd_enable_homedirs=1 httpd_ssi_exec=1 httpd_tty_comm=0 httpd_unified=1

Set SELinux boolean value using setsebool command as shown below. Make sure to restart the HTTP service after this change.

setsebool httpd_disable_trans 1

service httpd restart

"

naikel commented 7 years ago

None of that would work. If you're exploiting run-as, you are in the u:r:runas:s0 context, and you can't even write a file there.

I think you are lost. First we need to get at least u:r:kernel:s0 or u:r:init:s0 root access, and after that we can start talking about disabling SELinux. But at this point, we gain root access, but we can't even write a single file.

EDIT: You didn't read the thread. We already tried that. See the past posts, for example:

10-24 23:40:22.933 10954 10954 W run-as : type=1400 audit(0.0:728): avc: denied { setenforce } for uid=0 scontext=u:r:runas:s0 tcontext=u:object_r:kernel:s0 tclass=security permissive=0

That's what happens when you try to disable SELinux. It's one of the very first posts.

turnerrocks1 commented 7 years ago

http://android.stackexchange.com/questions/124857/selinux-and-chroot-system-call

turnerrocks1 commented 7 years ago

Is it because of SELinux?

I don't know - I am new (very new - one week old) to SELinux. I thought that when you put it to sleep (getenforce reporting "Permissive") it no longer interferes...

Apparently, I was wrong. Down the rabbit hole we go again...

Could it be because of my process context?

Remember that id returned... "uid=0(root) gid=0(root)... context=u:r:shell:s0"

Can I change that context? Being root and all, can I move away from shell? And if so, move to what?

The answer to the first question is runcon:

shell@K01E_2:/ $ runcon u:r:debuggerd:s0 /sbin/su

root@K01E_2:/ # id uid=0(root) gid=0(root)... context=u:r:debuggerd:s0

Good. But what context will allow me to mount and chroot?

Reading some more about SELinux, back in my main machine, I parse the /sepolicy file on the root of the initrd.img:

linuxbox$ $ sesearch -A sepolicy | grep chroot allow init_shell init_shell : capability { chown sys_chroot ... allow init init : capability { chown dac_read_search sys_chroot ... allow kernel kernel : capability { chown dac_override sys_chroot ... allow asus-dbug-d asus-dbug-d : capability { chown sys_chroot ... ...

OK, a number of possibilities! Especially that kernel one seems promising:

shell@K01E_2:/ $ runcon u:r:kernel:s0 /sbin/su

root@K01E_2:/ # id uid=0(root) gid=0(root)... context=u:r:kernel:s0

root@K01E_2:/ # chroot /data/debian/ /bin/bash
chroot() fail Operation not permitted

Darn.

Who the heck is blocking me from chrooting?

Any advice most welcome...

turnerrocks1 commented 7 years ago

ive created rooting apps for android 4.4-5.1 i havent made one since and also made a script root no exploits via sideloading in twrp and i havent been on android since ive been on ios since 2008 -2014 and just now restarting last time i created a jailbreak was when ios spoke Objectice-C now its swift and android im only used to java thats why i create root apps not C so sorry for wrong input but im just trying to help and if you dont believe me check my old website about 2 years old htcdesire626srootbyturnerhackz1.weebly.com and my youtube first root video got 16k views with 71 subs on a universal root script for all htc devices based on htc desire 626s but sorry for waste of time

turnerrocks1 commented 7 years ago

and im a linux kernel exploit researcher i do write C and know fundamentals and a short specialist in C++ and ruby and php but my specialty is java and js

naikel commented 7 years ago

Good. But what context will allow me to mount and chroot?

Read the policy (.te files) that will help you a lot. There are several approaches discussed here. Your approach would require you to get the context u:r:kernel:s0 and then transition to u:r:init:s0 to mount.

I think only the init context can mount. Nothing else. I've read many .te files and now I can't remember what context can do what.

There's the approach of getting the u:r:system_server:s0 context (that's easy) and try to flash the recovery partition and then reboot recovery.

Basically you have to read the .te files and figure out what could you do to cheat SELinux.

turnerrocks1 commented 7 years ago

@naikel i got an idea now that i look at previous root apps and my history of rooting busybox and tools supolicy tools and su always make a way my idea is not at all to cheat but evil face idea * but to use sepolicy itself according to my memory when i pushed dex tools and busybox and su and super su and supolicy ok now heres the part we can figure out there are 8 steps*

Step1:install supersu i remember that pingpong root after opening and exploiting a socket it required supersu almost instantly it was at root level which is uid and guid and suid 0 but it couldnt manage su nor install it so... it need supersu

Step2: Understanding when su nor busybox isnt installed super su will require twrp install update or su this can be avoided is we push busybox to /data/local/tmp along with tools and supolicy with the install-recovery.sh of supersu.zip or rar

Step3: once super and its rightful properties in /data/local/tmp are there we can run supersu app at the same time run adb use busybox

Step4: reboot after installing supersu

Step5: rerun the dirtyc0w exploit but use the code that is required on linux run /* ####################### dirtyc0w.c ####################### $ sudo -s

echo this is not a test > foo

chmod 0404 foo

$ ls -lah foo -r-----r-- 1 root root 19 Oct 20 15:23 foo $ cat foo this is not a test $ gcc -pthread dirtyc0w.c -o dirtyc0w $ ./dirtyc0w foo m00000000000000000 mmap 56123000 madvise 0 procselfmem 1800000000 $ cat foo m00000000000000000 ####################### dirtyc0w.c ####################### */

but of course we cant run sudo or su not really needed create a file with chmod 400 on android in /data/local/tmp do the above echo and ls run the ndk compiled exploit but instead use the file created with the echo of foo m000000000000000000 those are char maps and mips of memory should properaly work and this time run adb shell id if group is 0 then try mount /system rw and *could you send me a ndk compiled version of the exploit so i can further test it

naikel commented 7 years ago

None of that would work.

Due to SELinux, the only way that su works with the correct privilege is if it's located at /system/xbin/su. If the su binary is located anywhere else, like /data/local/tmp, even if it's owned by root and has the setuid bit on, it won't escalate privileges.

Now as you are aware /system is ro. So to do all this you need to gain root in the correct SELinux context to remount /system and copy su in /system/xbin/su.

So far we have gained root access but no within a context that let us create a file, even if it's in /data/local/tmp. SELinux allows shell user to write to /data/local/tmp, but root user (from the u:r:runas:s0 context) can't write to it!!! That's how SELinux is.

SELinux is a pain.

The recovery approach seems to work but I'm not brave enough to try it. This is it: https://github.com/jcadduono/android_external_dirtycow

Manouchehri commented 7 years ago

I don't think a custom recovery is needed.

shell@flo:/data $ getprop | grep -E 'secure|debuggable|build.type'
[ro.adb.secure]: [0]
[ro.build.type]: [user]
[ro.debuggable]: [1]
[ro.secure]: [0]
naikel commented 7 years ago

@Manouchehri so, how you did it, without a custom recovery?

ghost commented 7 years ago

@naikel he have it since day 1. @christianrodher : "@Manouchehri do you plan to post the compatible version?" @Manouchehri : "Not within the next few days. Maybe next month."

naikel commented 7 years ago

I wonder what is the context where applypatch runs when using ctl.start and launching a flash_recovery service... That's thought number 1.

Thought number 2. If I change the seclabel of, let's say, ueventd in /init.rc (I think runas context can read that file) and then ctl.stop ueventd, ctl.start ueventd, can I choose the kernel/init context?

ghost commented 7 years ago

error when compiling... any help /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:79: undefined reference to getcon' /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:87: undefined reference tosetcon' /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:95: undefined reference to getcon' /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:121: undefined reference toproperty_set'

naikel commented 7 years ago

@christianrodher you need the NDK for that, the UXTerm + gcc trick won't help you.

setcon/getcon are defined in selinux/selinux.h

jfranchetto commented 7 years ago

We can use Dirtycow to modify the default.prop file so that the ADB shell itself has root access, but those settings are loaded from the file at boot time if I'm not mistaken, so that's useless.

I wonder if we can swap out getprop with a version of our own that returns the values we want, giving us a root ADB shell...

ghost commented 7 years ago

@naikel can u send me your selinux.h... i tried a couple and still got the error

naikel commented 7 years ago

@christianrodher https://android.googlesource.com/platform/external/libselinux/+/android-6.0.1_r70/include/selinux/selinux.h

But if you don't have that in your development enviroment your project won't link to the library. You need the include files, the library files, etc.

@jfranchetto you mean to patch /system/libselinux.so? hmmm....

EDIT: I think even if you change libselinux.so it won't work since it makes kernel calls...

Manouchehri commented 7 years ago

@jfranchetto Yep, that works. https://github.com/timwr/CVE-2016-5195/issues/9#issuecomment-256776647

jfranchetto commented 7 years ago

@Manouchehri did you have to modify libc?

It doesn't seem sufficient to just replace getprop in system/bin since not everything looking for properties will use it to get them (namely ADB in this case).

I've seen that the ADB root checks eventually call into into things like system_property_read and system_property_get in libc/bionic/system_properties.cpp. Would it then not be sufficient to change those methods to just return the value we want for those particular flags?

ghost commented 7 years ago

@naikel did you manage to compile recowvery-app_process64.c? im using android-ndk-r13 putting selinux/selinux.h in the include folder and still getting the same errors. ./obj/local/arm64-v8a/objs/recowvery-app_process64/recowvery-app_process64.o: In function main': /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:79: undefined reference togetcon' /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:87: undefined reference to setcon' /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:95: undefined reference togetcon' /root/Desktop/android_external_dirtycow-android-6.0/./recowvery-app_process64.c:121: undefined reference to `property_set' clang++: error: linker command failed with exit code 1 (use -v to see invocation) /root/Desktop/android-ndk-r13/build/core/build-binary.mk:715: recipe for target 'obj/local/arm64-v8a/recowvery-app_process64' failed make[1]: *\ [obj/local/arm64-v8a/recowvery-app_process64] Error 1 make[1]: Leaving directory '/root/Desktop/android_external_dirtycow-android-6.0' Makefile:5: recipe for target 'build' failed

rhcp011235 commented 7 years ago

Instead of everyone spinning their wheels. Why doesn't the people who got it share?

naikel commented 7 years ago

@christianrodher no, I haven't tried to compile it because I don't have the NDK. All I've been compiling was with UXTerm + clang.

ghost commented 7 years ago

@naikel any idea of what im missing?

refi64 commented 7 years ago

@christianrodher Your NDK installation might be somehow screwed up. It should be linking with libselinux. Out of curiosity, how exactly are you invoking ndk-build?

ghost commented 7 years ago

@kirbyfan64 witth the provided files android.mk include $(CLEAR_VARS) LOCAL_MODULE := recowvery-app_process64 LOCAL_SRC_FILES := \ recowvery-app_process64.c LOCAL_CFLAGS += -DDEBUG LOCAL_SHARED_LIBRARIES := liblog libcutils libselinux LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog include $(BUILD_EXECUTABLE)

makefile all: build

build: ndk-build NDK_PROJECT_PATH=. APP_BUILD_SCRIPT=./Android.mk APP_PLATFORM=android-21

Manouchehri commented 7 years ago

@jfranchetto adbd on user builds does not check the ro.adb.secure, ro.debuggable and ro.secure flags (the instructions in gray do not exist); it will always drop drop capabilities (prctl).

secondary__z8adb_mainii vs _z8adb_mainii

jfranchetto commented 7 years ago

@Manouchehri Interesting...so that means changing the methods in libc would also be useless.

I mean, unless we could change the build type to be something other than user so we force ADB to check, I'm not sure I understand why those four properties are useful.

Manouchehri commented 7 years ago

@jfranchetto adbd is a static binary, doesn't link anything.

naikel commented 7 years ago

In 6.0.1 the adbd rules contain:

# No transitions from adbd to non-shell domains. adbd only ever
# transitions to the shell domain. In particular, we never want
# to see a transition from adbd to su (aka "adb root")
neverallow adbd { domain -shell }:process transition;
neverallow adbd { domain userdebug_or_eng(`-su') }:process dyntransition;

So adbd root is a no-no.

turnerrocks1 commented 7 years ago

@naikel help me understand something would you as i cloud remember zergrush exploited zerglings to root without selinux but instead echoing ro.kernel.qemu=0 while with root but without su and not even mentioning selinux so does that mean this exploit would only work with >=6.0 because or was selinux inplemented strongly in 6 or 5 i remember 4.4 android only instilled aslr and mmpap randomalization

ghost commented 7 years ago

the .c code to flash a block is there. it works on all.. that same need little modification to extract a a block.... so dirtycow can root any android one way or the other....

anyone manager to compile recowvery-app_process64?

Apology11 commented 7 years ago

@christianrodher do you have problems linking libselinux, liblog and libcutils when compiling recowvery-app_process64, too?

jfranchetto commented 7 years ago

@Manouchehri I can give it a try, looks like Dirtycow is unable to open /sbin/adbd though.

ghost commented 7 years ago

@Apology11 yes it doesnt link im reinstalling my ndk to check again.

Manouchehri commented 7 years ago

Justin: run-as can.

On Oct 28, 2016 8:57 AM, "Justin Franchetto" notifications@github.com wrote:

@Manouchehri https://github.com/Manouchehri I can give it a try, looks like Dirtycow is unable to open /sbin/adbd though.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/timwr/CVE-2016-5195/issues/9#issuecomment-256913603, or mute the thread https://github.com/notifications/unsubscribe-auth/AG5cogrzs-pPdE2kd6Pb1ETab9NVZ8Gjks5q4fFMgaJpZM4KfUon .

ghost commented 7 years ago

@Manouchehri run-as -exec dirtycow /sbin/adbd /data/local/tmp/adbd dont work.

what run-as are you using?

Manouchehri commented 7 years ago

No, I mean replace run-as with a binary that does the dirtycow exploit.

On Oct 28, 2016 10:07 AM, "christianrodher" notifications@github.com wrote:

@Manouchehri https://github.com/Manouchehri run-as -exec dirtycow /sbin/adbd /data/local/tmp/adbd dont work.

what run-as are you using?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/timwr/CVE-2016-5195/issues/9#issuecomment-256929248, or mute the thread https://github.com/notifications/unsubscribe-auth/AG5cokKq3XtrBNgLwBNL0uB9iu8iPzoiks5q4gGegaJpZM4KfUon .

ghost commented 7 years ago

@Manouchehri not in BLU R1 HD run-as is dirtycow run-as /sbin/adbd /data/local/tmp/adbd-no-drop < could not open /sbin/adbd

naikel commented 7 years ago

You can write a simple shell to run as run-as:

shell@victara:/data/local/tmp $ run-as
cd /sbin
ls -l
-rwxr-x--- root     root       256748 1969-12-31 20:00 adbd
-rwxr-x--- root     root       268636 1969-12-31 20:00 healthd
lrwxrwxrwx root     root              1969-12-31 20:00 ueventd -> ../init
lrwxrwxrwx root     root              1969-12-31 20:00 watchdogd -> ../init

This one worked for me: https://github.com/brenns10/lsh

You can add a pretty prompt if you want (mine does not have prompt).

After that you can play a little bit more with the run-as context, and replace adbd running dirtycow on it.

alien0x00 commented 7 years ago

@naikel Will adbd able to bypass SELinux?

naikel commented 7 years ago

@alien0x00 I don't think so, by reading the adbd.te file. Also the adbd from @Manouchehri is significantly larger than the one in my device, so replacing it using dirtycow won't work.

jfranchetto commented 7 years ago

@naikel Good to know that you couldn't replace it. I made a version of run-as that will call dirtycow to replace adbd but for some reason setresuid(0,0,0) isn't working (even if I use the original run-as from the PoC), so I couldn't even try to replace adbd.

naikel commented 7 years ago

@Manouchehri it's a MotoX with Android 6.0.1:

-rwxr-x--- root root 256748 1969-12-31 20:00 adbd

I was thinking that using the install_recovery.sh - applypatch approach, instead of flashing a new recovery.img, you could run dirtycow within the recover context directly on the block device:

  allow recovery device:dir r_dir_perms;
  allow recovery block_device:dir r_dir_perms;
  allow recovery dev_type:blk_file rw_file_perms;

But I wonder how persistent would those changes be.

ghost commented 7 years ago

@naikel the sh source compiled perfect but dont work. it stay stucked in run-as till i press ctrl+c

naikel commented 7 years ago

@christianrodher are you sure it doesn't work? Type something! don't wait for the prompt (if you want prompt you would have to fix flushing the stdout a little bit I guess).

ghost commented 7 years ago

@Manouchehri was you able to compile recowvery-app_procress64.c?

also trying to dirtycow your adbd it seems imposible lol

shell@R1_HD:/data/local/tmp $ run-as -exec toybox                              
Current uid: 2000
Setting capabilities
Attempting to escalate to root
Current uid: 0
Executing: 'toybox' with 0 arguments

usage toybox /default.prop /data/local/tmp/default.prop
shell@R1_HD:/data/local/tmp $ run-as -exec toybox /sbin/adbd /data/local/tmp/adbd-no-drop                         <
Current uid: 2000
Setting capabilities
Attempting to escalate to root
Current uid: 0
Executing: 'toybox' with 2 arguments

could not open /data/local/tmp/adbd-no-drop
Manouchehri commented 7 years ago

@naikel ah right, that makes sense. Mine is a Nexus 7. I'll probably have to debug this myself next week then.

Doesn't @jcadduono's repo work for flashing recoveries? He's already posted how to switch to the system_server context from app_process.

Manouchehri commented 7 years ago

@christianrodher Put adbd-no-drop in another (larger) file first. I believe I used a random bin from pittpatt to overwrite.

ghost commented 7 years ago

@Manouchehri it works but no one seems to be able to compile recowvery-app_progress64 and the one he uploaded compiled isn't my arch.

can you try? armeabi-v7a