Skip to content

1x02 - 权限模型演进

Android 的权限模型经历了从“全家桶式授予”到“按需动态申请”的重大演进。它是应用沙箱在业务逻辑层面的延伸。

1. 权限等级 (Protection Levels)

Android 将权限分为四个主要等级,决定了系统如何授予这些权限:

  • Normal (普通权限): 风险较低,安装时自动授予(如访问网络、设置闹钟)。
  • Dangerous (危险权限): 涉及用户隐私(如摄像头、联系人、位置)。必须在运行时由用户明确授权。
  • Signature (签名权限): 只有当请求权限的应用与声明权限的应用签名相同时,系统才会授予。常用于系统应用间的私密通信。
  • Privileged (特权权限): 预装在系统分区(如 /system/priv-app)的应用才能申请。

2. 权限到 GID 的映射机制

在底层,许多权限最终会转化为 Linux 的 GID (Group ID)

2.1 platform.xml 的作用

系统配置文件 /etc/permissions/platform.xml 定义了权限与 GID 的映射关系:

xml
<permission name="android.permission.INTERNET" >
    <group gid="inet" />
</permission>
<permission name="android.permission.READ_EXTERNAL_STORAGE" >
    <group gid="sdcard_r" />
</permission>

当应用被授予 INTERNET 权限时,它的进程会被加入到 inet 组(GID 3003)。内核根据进程的 GID 列表来决定其是否可以打开网络 Socket。

3. 运行时权限 (Android 6.0+)

从 Android 6.0 (API 23) 开始,危险权限不再在安装时授予,而是在应用运行时弹出对话框。

  • 底层实现: 权限状态存储在 /data/system/packages.xml(Android 12 前)或 /data/misc_de/<userId>/apexdata/com.android.permission/runtime-permissions.xml(Android 12+)中。当用户点击”允许”时,PermissionManagerService 会更新该应用的权限位。
  • 撤销机制: 用户可以随时在设置中撤销权限。系统会通过重启应用进程来确保权限变更立即生效(因为 GID 列表只能在进程创建时设置)。

4. 权限审计:dumpsys package

安全研究员可以使用 adb 工具快速查看应用的权限状态:

bash
# 查看特定应用的权限授予情况
adb shell dumpsys package com.example.app | grep -A 20 "requested permissions"

输出示例:

text
requested permissions:
  android.permission.CAMERA
  android.permission.RECORD_AUDIO
install permissions:
  android.permission.INTERNET: granted=true
runtime permissions:
  android.permission.CAMERA: granted=false, flags=[ USER_SET ]
  android.permission.RECORD_AUDIO: granted=true, flags=[ USER_SET ]

5. 权限校验流程:从 checkPermission 到 PMS

当应用尝试执行敏感操作(如访问摄像头)时,系统会进行权限校验:

mermaid
sequenceDiagram
    participant App
    participant Framework
    participant PermMgr as PackageManagerService / PermissionManagerService
    participant Kernel
    
    App->>Framework: 调用敏感 API
    Framework->>Framework: Context.checkPermission()
    Framework->>PermMgr: ActivityManager.checkPermission() → 最终由 PMS/PermissionManager 查询权限状态
    PermMgr->>PermMgr: 检查内存权限表
    alt 权限已授予
        PermMgr->>Kernel: 验证 GID (如 inet)
        Kernel-->>PermMgr: 通过
        PermMgr-->>App: PERMISSION_GRANTED,继续执行
    else 权限未授予
        PermMgr-->>App: PERMISSION_DENIED → SecurityException
    end

关键步骤:

权限校验通过 PackageManagerService(或 Android 11+ 拆分出的 PermissionManagerService)直接完成,调用方通过 Context.checkPermission()ActivityManager.checkPermission() → 最终由 PMS/PermissionManager 查询权限状态。

  1. API 调用: 应用调用 Framework 接口。
  2. ContextImpl: 内部调用 Context.checkPermission()
  3. PackageManagerService (PMS) / PermissionManagerService: 权限校验由 PackageManagerService(Android 11 之前)或拆分出的 PermissionManagerService(Android 11+)直接完成,检查内存中的权限表,判断该 UID 是否拥有目标权限。
  4. 结果返回: 如果未授权,抛出 SecurityException

7. Canyie (残页) 相关 CVE

GitHub: https://github.com/canyie | Blog: https://blog.canyie.top

以下是 Canyie 发现的与权限/信息泄露相关的漏洞:

CVE类型简介公告
CVE-2024-43090ID/High权限状态信息泄露,可探测其他应用的权限授予情况ASB 2024-11
CVE-2025-0076ID/HighFramework 层敏感数据泄露,可获取其他用户/应用的私有信息ASB 2025-02
CVE-2025-48545ID/HighFramework 信息泄露,跨用户数据访问ASB 2025-06

:ID = Information Disclosure,常见利用场景包括:绕过 ASLR、探测应用安装状态、泄露用户隐私数据、为后续提权收集信息。

参考(AOSP)