应用沙盒

Android 平台利用基于用户的 Linux 保护机制来识别和隔离应用资源,可将不同的应用分隔开来,并保护应用和系统免受恶意应用的攻击。为此,Android 会为每个 Android 应用分配一个独一无二的用户 ID (UID),并在自己的进程中运行。

Android 会使用该 UID 设置一个内核级应用沙盒。内核会在进程级别利用标准的 Linux 机制(例如,分配给应用的用户 ID 和组 ID)实现应用和系统之间的安全防护。默认情况下,应用不能彼此交互,而且对操作系统的访问权限会受到限制。如果应用 A 尝试执行恶意操作(例如在没有权限的情况下读取应用 B 的数据或拨打电话),则操作系统会阻止此类行为,因为应用 A 没有相应的默认用户权限。这一沙盒机制非常简单,可审核,并且基于已有数十年历史的 UNIX 风格的进程用户隔离和文件权限机制。

由于应用沙盒位于内核层面,因此该安全模型的保护范围扩展到了原生代码和操作系统应用。位于更高层面的所有软件(例如,操作系统库、应用框架、应用运行时环境和所有应用)都会在应用沙盒中运行。某些平台会限制开发者只能使用特定的开发框架、API 或语言。在 Android 上,并没有为了执行安全防护机制而限制开发者必须如何编写应用;在这方面,原生代码与解释型代码一样进行沙盒化。

保护机制

通常,要在经过适当配置的设备上攻破应用沙盒这道防线,必须要先攻破 Linux 内核的安全功能。但是,与其他安全功能类似,强制执行应用沙盒的各种保护机制并非无懈可击,因此深度防御对于防止通过单个漏洞入侵操作系统或其他应用非常重要。

Android 依靠许多保护机制来强制执行应用沙盒。这些强制措施是随着时间的推移不断引入的,并且显著增强了基于 UID 的原始自主访问控制 (DAC) 沙盒的安全性。以前的 Android 版本包括以下保护机制:

  • 在 Android 5.0 中,SELinux 提供了强制访问控制 (MAC) 来将系统和应用分离开。但是,所有第三方应用都在相同的 SELinux 环境中运行,因此应用间的隔离主要由 UID DAC 强制执行。
  • 在 Android 6.0 中,SELinux 沙盒经过扩展,可以跨各个物理用户边界隔离应用。此外,Android 还为应用数据设置了更安全的默认设置:对于 targetSdkVersion >= 24 的应用,应用主目录上的默认 DAC 权限从 751 更改为 700。这为私有应用数据提供了更安全的默认设置(但应用可能会替换这些默认设置)。
  • 在 Android 8.0 中,所有应用都设为使用 seccomp-bpf 过滤器运行,该过滤器可限制允许应用使用的系统调用,从而增强应用/内核边界的安全性。
  • 在 Android 9 中,targetSdkVersion >= 28 的所有非特权应用都必须在不同的 SELinux 沙盒中运行,并针对各个应用提供 MAC。这种保护机制可以提升应用隔离效果,防止替换安全默认设置,并且(最重要的是)防止应用的数据可让所有人访问。
  • 在 Android 10 中,应用对文件系统只有未经处理的有限了解,且无法直接访问 /sdcard/DCIM 之类的路径。不过,应用保留对任何适用方法(例如 Context.getExternalFilesDir())返回的软件包专用路径的完整原始访问权限。

共享文件指南

将应用数据设为可供所有人访问从安全方面来讲是一种不好的做法,这会为所有人授予访问权限,并且无法限定只让目标受众访问这些数据。这种做法会导致信息披露泄露,让代理漏洞变得混乱,并会成为针对包含敏感数据的应用(例如电子邮件客户端)的恶意软件的首选目标。在 Android 9 及更高版本中,targetSdkVersion>=28 的应用明确禁止以这种方式共享文件。

在共享文件时,请遵循以下指南,而不是让应用数据可供所有人访问:

  • 如果您的应用需要与其他应用共享文件,请使用内容提供程序。内容提供程序会以适当的粒度共享数据,并且不会出现使用所有人都可访问的 UNIX 权限会带来的诸多问题(如需了解详情,请参阅内容提供程序基础知识)。
  • 如果您的应用包含确实应让所有人访问的文件(例如照片),则相应文件必须是媒体文件(仅限照片、视频和音频文件)且使用 MediaStore 类存储。(如需了解详情,请参阅 DAC 预览指南。)

存储运行时权限控制着通过 MediaStore 对强类型媒体集合的访问权限。如需访问弱类型文件(例如 PDF)和 MediaStore.Downloads 类,应用必须使用 ACTION_OPEN_DOCUMENT intent 之类的 intent。

要实现 Android 10 行为,请使用 requestLegacyExternalStorage 清单属性,并遵守应用权限最佳做法

  • 对于以 Android 9(及更低版本)为目标平台的应用,清单标记的默认值为 true
  • 对于以 Android 10 为目标平台的应用,默认值为 false。要在以 Android 10 为目标平台的应用中暂时退出已过滤的存储空间视图,请将清单标记的值设置为 true
  • 使用受限权限,安装程序会将允许使用未进行沙盒化的存储的应用加入白名单。未加入白名单的应用会被沙盒化。