Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

/system is "ro" on Mavic, Phantom4, and others for specific firmware versions #5

Closed
MAVProxyUser opened this issue Jul 4, 2017 · 16 comments

Comments

@MAVProxyUser
Copy link
Owner

MAVProxyUser commented Jul 4, 2017

We are currently unable to write to /system for an easy kill on many of the systems and firmware versions...

As such it is critical to figure out how to use /data /cache /tmp or other writable locations to leverage root and enable ADB access .

Special android files may be good targets:
/dev/properties perhaps?
https://chengyihe.wordpress.com/2016/12/05/android-persist-system-properties/'

/data/property/* maybe?
https://chengyihe.wordpress.com/2016/12/05/android-how-system-properties-are-loaded-at-boot-time/

We can possibly extract the /init.rc from update files to help check for "rw" partitions in specific versions?

(on Spark for example logged in as root)
root@wm100_dz_ap0001_v5:/ # grep mount /init*
Binary file /init matches
/init.rc: mount tmpfs tmpfs /tmp size=32M
/init.rc: mount tmpfs tmpfs /var size=2M
/init.rc: mount tmpfs tmpfs /ftp size=1M
/init.rc:# mount ext4 /dev/block/platform/comip-mmc.1/by-name/userdata /ftp/upgrade wait rw
/init.rc:# mount ext4 /dev/block/platform/comip-mmc.1/by-name/blackbox /ftp/blackbox sync rw
/init.rc:# mount debugfs nodev /sys/kernel/debug wait rw
/init.rc:# mount vfat /dev/block/mmcblk1p1 /sdcard nowait rw
/init.rc: mount ext4 /dev/block/platform/comip-mmc.1/by-name/amt /amt wait ro
/init.rc: mount ext4 /dev/block/platform/comip-mmc.1/by-name/userdata /data wait rw
/init.rc: mount ext4 /dev/block/platform/comip-mmc.1/by-name/vendor /vendor wait ro
/init.rc:# mount ext4 /dev/block/platform/comip-mmc.1/by-name/blackbox /blackbox sync rw
/init.rc:# mount ext4 /dev/block/platform/comip-mmc.1/by-name/system /system wait ro
/init.rc: mount ext4 /dev/block/platform/comip-mmc.1/by-name/system /system wait rw
/init.rc:# mount ext4 /dev/block/platform/comip-mmc.1/by-name/cache /cache wait rw
/init.rc:# mount vfat /dev/block/platform/comip-mmc.1/by-name/udisk /sdcard nowait rw
/init.rc:# mount vfat /dev/block/mmcblk0p18 /sdcard wait rw
/init.rc: mount rootfs rootfs / ro remount
/init.rc: mount ext4 /dev/block/platform/comip-mmc.1/by-name/system /system wait rw

@MAVProxyUser
Copy link
Owner Author

We've now got some solid leads via /data/

By default there is no /data/property when it exists... things get fun
root@wm220_dz_ap0002_v1:/ # ls /data/property/
root@wm220_dz_ap0002_v1:/ # setprop persist.service.adb.debuggable 1
root@wm220_dz_ap0002_v1:/ # setprop persist.service.adb.enable 1
root@wm220_dz_ap0002_v1:/ # ls /data/property/
persist.service.adb.debuggable
persist.service.adb.enable
root@wm220_dz_ap0002_v1:/ # cat /data/property/*
11

In theory we can create tar files with persistent properties present.

@MAVProxyUser
Copy link
Owner Author

MAVProxyUser commented Jul 5, 2017

Ok folks... we are having some progress writing to /data/properties We need just a LITTLE help from folks that understand android and we can likely have some success on ALL platforms. What we found is that DJI seems to have removed the /data/property folder and as such no persistent settings are maintained.

This will give you a basic understanding of android properties...
https://chengyihe.wordpress.com/2016/12/05/android-readwrite-system-properties/
https://chengyihe.wordpress.com/2016/12/05/android-persist-system-properties/

To test the theory out... I used a craft I already have root on and created the /data/property folder (which we can do via the tar file and other methods)
root@wm220_dz_ap0002_v1:/data/ # mkdir /data/property
root@wm220_dz_ap0002_v1:/data/ # setprop persist.service.adb.debuggable 1
root@wm220_dz_ap0002_v1:/data/ # setprop persist.service.adb.enable 1
root@wm220_dz_ap0002_v1:/data/ # setprop persist.sys.usb.config rndis,mass_storage,bulk,acm,adb

I did an adb pull of the /data/property directory so I could examine it.

 root@wm220_dz_ap0002_v1:/data/property # ls -al
-rw------- root     root            1 1980-01-01 00:37 persist.service.adb.debuggable
-rw------- root     root            1 1980-01-01 00:36 persist.service.adb.enable
-rw------- root     root           31 1980-01-01 00:37 persist.sys.usb.config
$ ls
persist.service.adb.debuggable	persist.service.adb.enable	persist.sys.usb.config
$ xxd persist.service.adb.debuggable 
00000000: 31                                       1
$ xxd persist.service.adb.enable 
00000000: 31                                       1
$ xxd persist.sys.usb.config 
00000000: 726e 6469 732c 6d61 7373 5f73 746f 7261  rndis,mass_stora
00000010: 6765 2c62 756c 6b2c 6163 6d2c 6164 62    ge,bulk,acm,adb

Upon rebooting the drone it was immediately clear the properties took hold as the boot was different. We don't fully understand the process, but are digging in. As an example at one point we reduced the power of the ADB shell (that was obtained via different exploit means) to NOT be root via "service.adb.root [1]"
shell@wm220_dz_ap0002_v1:/ $

Reading the source to init has helped... specifically their comment on writable directories leading to security bugs.
https://android.googlesource.com/platform/system/core/+/kitkat-release/init/init.c
https://android.googlesource.com/platform/system/core/+/kitkat-release/rootdir/init.rc

# IMPORTANT: Do not create world writable files or directories.
# This is a common source of Android security bugs.

Right now we need to keep digging into how the internals of the android boot process work, any help is welcome! https://chengyihe.wordpress.com/2016/12/05/android-how-system-properties-are-loaded-at-boot-time/

@Bin4ry
Copy link

Bin4ry commented Jul 6, 2017

Well the /data/property way is no good to gain root, only persistent vars are saved there and adb will check for service.adb.root without persistent, see here: https://android.googlesource.com/platform/system/core/+/f85f111620afba9bad222661c1c34aee731d415b/adb/adb_main.cpp

so all you could do is enabling adb through the exploit like you already showed. One exception here, if the device is running android4 you would be able to create a file /data/local.prop with the contents:
ro.secure=0

we exploited this back in the time when android4 was the real deal ;)
So if the drone is based on 4.0 you might be able to combine the /data/property/... and /data/local.prop to gain full adb root.

Another way is to try to play with the recovery commands, once you are in recovery you MIGHT be lucky that there is an adb root shell. But this depends on how tight security was made in production ;-)
To help you guys there i would need a copy of the images, init ramdisk, system image etc. or atleast a link where i can grab them and extract them myself. I found some parts at droner69's repo, but not all of it. Since i want to see the config files too. For example if you are lucky they added some custom script to udhcp or such. But hard to tell without the system images ;-)
There might actually be a few programs which can execute scripts on triggers, but we need to see if there are scripts calling this programs with config files being called from positions where you have write access.

But a question here, i did only a quick look so i am not sure. If i understood the exploit correct you are doing a symlink putting it into the tar, then removing it, create a folder with the same name as the symlink and a file you want to create and after that you are setting the permissions of the file to 755 here right?
system("chmod 755 " + "symlink/" + destfile ). After the untar is done the file is on the filesystem with this permission, correct?

why not do this:
the exploited dji app runs as root right or not? If so ->
Create a sh script instead of a file (do this inside the /data/local/tmp folder, in this folder you can execute scripts!). Give it not 755 but 06755. but use cmdline option -p to preserver file permission into the tarball. Now also add your persistent adb permissions to bring a normal non-root adb shell up. After that you can run the sh script and should have # .

Best Regards
Bin4ry
 

@MAVProxyUser
Copy link
Owner Author

@Bin4ry the system is based on KitKat 4.4.4���

[ro.build.description]: [full_wm220_dz_ap0002_v1-userdebug 4.4.4 KTU84Q eng.jenkins.20170619.214217 test-keys]

@MAVProxyUser
Copy link
Owner Author

@Bin4ry Create a sh script instead of a file (do this inside the /data/local/tmp folder, in this folder you can execute scripts!) �� Why are scripts magically executable in /data/local/tmp ? What runs them automagically? ��

The problem we've been having thus far is it does not seem that adb gets kicked off properly via properties files alone... When ADB starts it is already root FWIW. no extra fuckery required. We simply need it to kick off.

@Bin4ry
Copy link

Bin4ry commented Jul 6, 2017

@MAVProxyUser no they are not started automatically, i meant in this folder they are executeable. In some other folders this maybe prevented (depending on the android verison!), that was the reason i wrote that.

So if you inject the persistent parameters you do not get an adb shell with user privs? You normally should get it. Only if you have service.adb.root=1 it will come up as root when ro.secure=0.

So we should focus on getting an adb shell at all, if we get that we might be able to use some old kernel exploit targeting the platform, maybe something like towelroot will work. So what values are you writing to properties in your tests? the 3 values you posted in your test should bring up adb imho. But that is one of the reasons we should take a look into the init scripts. We may get an answer here ;)

@MAVProxyUser
Copy link
Owner Author

MAVProxyUser commented Jul 6, 2017

@Bin4ry "So we should focus on getting an adb shell at all" as it stands the other ADB access we have (via different non public exploit path) does drop straight to root ADB access.

This bug pops root on Spark due the writable /system. It has been harder on the others. IF we figure a place to drop a file / create one that will allow us to execute a command we should be rocking out. �

"the 3 values you posted in your test should bring up adb imho" does it run on all consoles? maybe it is running on ttyS0 instead of the USB port?

I wish you could use "ctrl.start" via persist! Attached are the kernel logs from the tests @Mavic129 did.
mavic_kernel_log_after_adding_persist_prop_in_data.txt

@MAVProxyUser
Copy link
Owner Author

@Bin4ry Are there any properties or files (similar to the old fstab) on KitKat that can be used to influence how vold mounts partitions?

@Bin4ry
Copy link

Bin4ry commented Jul 6, 2017

IIRC there are no config files to manipulated mounts in the area where you are able to write.

from the kernel log it seems that adb is up. are you sure it was not there? maybe there was just an connection issue on the pc side? (windows user? maybe driver issue?)
<6>[ 1.653691] c0 1 (init) android functions_store: rndis,mass_storage,bulk,acm,adb
...
<6>[ 1.655853] c0 1 (init) adb_bind_config
...
<6>[ 1.675952] c0 113 (adbd) adb_open

so it did indeed work to start adbd on the device. Please verify again if it is really not possible to connect to the device, because even if you have a non-root adb shell it should be easy to get root from there. There are many ways to do once you can run commands from a shell ;-)

Will try to extract the firmware files i found in droner69's repo and see if i get some ideas from it.

@MAVProxyUser
Copy link
Owner Author

Two of us have verified, for some reason it is not starting with just the props, even though it claims it did. @Mavic129 is the other person.

@MAVProxyUser
Copy link
Owner Author

I'm noticing I am getting new /dev/ device files... I wonder if the ADB serial connection gets confused somehow. Can you specify serial port adb uses?

@Bin4ry
Copy link

Bin4ry commented Jul 6, 2017

This is not standard for adbd. it can however be connected to tcpip, but that would need to be initiated through usb first (or through prop on system partition :D :D )
Which firmware version was this drone running? I can see some differences to your scripts on the git and the scripts in the 900 firmware. However, it seems that dji managed to sign the firmware with testkeys. Check /system/etc/security/otacerts.zip.
So let's play an idea here. If we do an ota.zip signed with known test-keys we can add
"--update_package=/cache/ota.zip" to /cache/recovery/command
NOW we "only" need to reboot into recovery mode and it will install "our" ota.zip ;) from this ota.zip we could change parameters on /system as we wish.
Still we would need to be able to boot into recovery, maybe there is an "key combo" to do this, i don't really know (on most phones there is ;) ). Another way would be through some init script conditions, but i am not able to extract the ramdisk from the images. So could you please dump the init-ramdisk for me (a filesystem copy from a running device should be enough). thanks

EDIT: here some info about ota files:
https://source.android.com/devices/tech/ota/inside_packages

With the scripts we can manage to change system partition very easy. We only would need to trigger a recovery boot somehow as we can sign the ota.zip with testkeys very easy and we can put it to cache with the tar exploit

@MAVProxyUser
Copy link
Owner Author

This issue has been fixed... 94e6f2c

confirmed we just rooted Mavic with RedHerring. Phantom4 series, Mavic Pro, Inspire 2, and Spark #Jailbreak all vulnerable now.

$ sudo ./RedHerring.rb /data/.bin/grep grep

@Bin4ry
Copy link

Bin4ry commented Jul 6, 2017

Hey,

wow you found a nice location there, congrats :-) Let's see what they will change in the next firmware. I would like to speak to you guys in a more private way if possible so we can maybe think together about future releases.

@Bin4ry
Copy link

Bin4ry commented Jul 6, 2017

Hey,
thanks for the link but the invite link seems to be no longer active.

Best Regards

@fvantienen
Copy link

Repository owner deleted a comment from fvantienen Jul 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants