对导出的组件的基于权限的访问控制
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
OWASP 类别: MASVS-PLATFORM:平台互动
概览
Android 权限是应用清单中声明的字符串标识符,用于请求访问受限数据或执行受限操作,由 Android 框架在运行时强制执行。
Android 权限级别表示与权限相关的潜在风险:
- 普通:低风险权限,会在安装时自动授予
- 危险:可能允许访问敏感用户数据的高风险权限,需要在运行时获得用户明确批准
- 签名:仅向使用与声明权限的应用相同的证书进行签名的应用授予,通常用于系统应用或同一开发者的应用之间的互动
当应用的组件(如 activity、接收器、content provider 或服务)符合以下所有条件时,就会发生与基于权限的访问权限控制相关的漏洞:
- 组件未与
Manifest
中的任何 android:permission
相关联;
- 组件执行敏感任务,并且用户已批准相应权限;
- 组件已导出;
- 该组件不会执行任何手动(清单级或代码级)权限检查;
在这种情况下,恶意应用可以滥用易受攻击组件的权限,将易受攻击应用的权限代理给恶意应用,从而执行敏感操作。
影响
导出易受攻击的组件可能会被用于获取敏感资源的访问权限或执行敏感操作。此不良行为的影响取决于易受攻击组件及其权限的上下文。
缓解措施
需要敏感任务的权限
导出具有敏感权限的组件时,请对任何传入请求都要求使用相同的权限。Android Studio IDE 针对接收器和服务提供了 lint 检查,以发现此漏洞并建议您要求适当的权限。
开发者可以通过在 Manifest
文件中声明权限,或在实现服务时在代码级别声明权限,来要求传入请求具有相应权限,如以下示例所示。
Xml
<manifest ...>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application ...>
<service android:name=".MyExportService"
android:exported="true"
android:permission="android.permission.READ_CONTACTS" />
</application>
</manifest>
Kotlin
class MyExportService : Service() {
private val binder = MyExportBinder()
override fun onBind(intent: Intent): IBinder? {
// Enforce calling app has the required permission
enforceCallingPermission(Manifest.permission.READ_CONTACTS, "Calling app doesn't have READ_CONTACTS permission.")
// Permission is enforced, proceed with export logic
return binder
}
// Inner class for your Binder implementation
private inner class MyExportBinder : Binder() {
// Permission is enforced, proceed with export logic
}
}
Java
public class MyExportService extends Service {
@Override
public IBinder onBind(Intent intent) {
// Enforce calling app has the required permission
enforceCallingPermission(Manifest.permission.READ_CONTACTS, "Calling app doesn't have READ_CONTACTS permission.");
return binder;
}
// Inner class for your Binder implementation
private class MyExportBinder extends Binder {
// Permission is enforced, proceed with export logic
}
}
不导出组件
除非绝对必要,否则请避免导出有权访问敏感资源的组件。为此,您可以将 Manifest
文件中的 android:exported
设置为组件的 false
。从 API 级别 31 及更高版本开始,此属性默认设为 false
。
Xml
<activity
android:name=".MyActivity"
android:exported="false"/>
采用基于签名的权限
当您在受您控制或归您所有的两个应用之间共享数据时,请使用基于签名的权限。此类权限不需要用户确认,而是会检查访问数据的应用是否使用相同的签名密钥进行了签名。此设置可提供更加精简、安全的用户体验。如果您声明自定义权限,请考虑相应的安全准则。
Xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<permission android:name="my_custom_permission_name"
android:protectionLevel="signature" />
单任务端点
遵循关注分离设计原则来实现应用。每个端点都应仅使用特定权限执行一小部分特定任务。这种良好的设计实践还允许开发者为每个端点应用精细的权限。例如,请避免创建一个同时提供日历和通讯录服务的端点。
资源
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-07-26。
[null,null,["最后更新时间 (UTC):2025-07-26。"],[],[],null,["# Permission-based access control to exported components\n\n\u003cbr /\u003e\n\n**OWASP category:** [MASVS-PLATFORM: Platform Interaction](https://mas.owasp.org/MASVS/09-MASVS-PLATFORM)\n\nOverview\n--------\n\nAn Android permission is a string identifier declared in the app's manifest to\nrequest access to restricted data or actions, enforced at runtime by the Android\nframework.\n\n[Android permission levels](/guide/topics/manifest/permission-element#plevel) indicate the potential risk associated with the\npermission:\n\n- **Normal**: Low-risk permissions, automatically granted at install time\n- **Dangerous**: High-risk permissions that could allow access to sensitive user data, requiring explicit user approval at runtime\n- **Signature**: Granted only to apps signed with the same certificate as the app declaring the permission, typically used for system apps or interactions between apps from the same developer\n\nVulnerabilities related to permission-based access controls occur when an app's\ncomponent (such as [activity](/reference/android/app/Activity), [receiver](/privacy-and-security/security-tips#broadcast-receivers), [content provider](/privacy-and-security/security-tips#content-providers), or\n[service](/privacy-and-security/security-tips#services)) meets all of the following criteria:\n\n- The component is not associated with any `android:permission` in the `Manifest`;\n- The component performs a sensitive task for which a permission exists that the user has already approved;\n- The component is exported;\n- The component does not perform any manual (manifest or code-level) permission checks;\n\nWhen this happens, a malicious app can perform sensitive actions by abusing the\nprivileges of the vulnerable component, proxying the vulnerable app's privileges\nto the malicious app.\n\nImpact\n------\n\nExporting vulnerable components can be used to gain access to sensitive\nresources or to perform sensitive actions. The impact of this unwanted behavior\ndepends on the context of the vulnerable component and its privileges.\n\nMitigations\n-----------\n\n### Require permissions for sensitive tasks\n\nWhen exporting a component with sensitive permissions, require those same\npermissions for any incoming request. The Android Studio IDE has lint checks for\n[receivers](https://googlesamples.github.io/android-custom-lint-rules/checks/ExportedReceiver.md.html) and [services](https://googlesamples.github.io/android-custom-lint-rules/checks/ExportedService.md.html) to spot this\nvulnerability and recommend requiring the appropriate permissions.\n\nDevelopers can require permissions for incoming requests either by declaring\nthem in the `Manifest` file or at code-level when implementing the service, as\nin the following examples. \n\n### Xml\n\n \u003cmanifest ...\u003e\n \u003cuses-permission android:name=\"android.permission.READ_CONTACTS\" /\u003e\n\n \u003capplication ...\u003e\n \u003cservice android:name=\".MyExportService\"\n android:exported=\"true\"\n android:permission=\"android.permission.READ_CONTACTS\" /\u003e\n\n \u003c/application\u003e\n \u003c/manifest\u003e\n\n### Kotlin\n\n class MyExportService : Service() {\n\n private val binder = MyExportBinder()\n\n override fun onBind(intent: Intent): IBinder? {\n // Enforce calling app has the required permission\n enforceCallingPermission(Manifest.permission.READ_CONTACTS, \"Calling app doesn't have READ_CONTACTS permission.\")\n // Permission is enforced, proceed with export logic\n return binder\n }\n\n // Inner class for your Binder implementation\n private inner class MyExportBinder : Binder() {\n // Permission is enforced, proceed with export logic\n }\n }\n\n### Java\n\n public class MyExportService extends Service {\n\n @Override\n public IBinder onBind(Intent intent) {\n // Enforce calling app has the required permission\n enforceCallingPermission(Manifest.permission.READ_CONTACTS, \"Calling app doesn't have READ_CONTACTS permission.\");\n\n return binder;\n\n }\n\n // Inner class for your Binder implementation\n private class MyExportBinder extends Binder {\n // Permission is enforced, proceed with export logic\n\n }\n }\n\n### Don't export the component\n\nAvoid exporting components with access to sensitive resources unless absolutely\nnecessary. You can achieve this by setting the `android:exported` in the\n`Manifest` file to `false` for your component. From [API level 31](/about/versions/12/behavior-changes-12#exported) and\nbeyond, this attribute is set to `false`by default. \n\n### Xml\n\n \u003cactivity\n android:name=\".MyActivity\"\n android:exported=\"false\"/\u003e\n\n### Apply signature-based permissions\n\nWhen sharing data between two apps that you control or own, use signature-based\npermissions. These permissions don't require user confirmation and, instead,\ncheck that the apps accessing the data is signed using the same signing key.\nThis setup offers a more streamlined, secure user experience. If you declare\ncustom permissions do consider the [corresponding security guidelines](https://developer.android.com/privacy-and-security/risks). \n\n### Xml\n\n \u003cmanifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n package=\"com.example.myapp\"\u003e\n \u003cpermission android:name=\"my_custom_permission_name\"\n android:protectionLevel=\"signature\" /\u003e\n\n### Single-task endpoints\n\nImplement your app by following the [Separation of Concerns](/topic/architecture#separation-of-concerns) design\nprinciple. Each endpoint should only perform a small set of specific tasks with\nspecific privileges. This good design practice also allows the developer to\napply granular permissions for each endpoint. For example, avoid creating a\nsingle endpoint that serves both calendar and contacts.\n\nResources\n---------\n\n- [Android Access to app protected components from the Oversecured blog](https://blog.oversecured.com/Android-Access-to-app-protected-components/)\n- [Content Provider Best Practices](/privacy-and-security/security-tips#content-providers)\n- [Runtime (Dangerous) Permissions](/guide/topics/permissions/overview#runtime)\n- [Separation of Concerns design principle](/topic/architecture#separation-of-concerns)\n- [Android permissions documentation](/guide/topics/manifest/permission-element#plevel)\n- [Android broadcast receivers security tips](/privacy-and-security/security-tips#broadcast-receivers)\n- [Android services security tips](/privacy-and-security/security-tips#services)\n- [Android 12 (API 31) exported default set to \"false\"](/about/versions/12/behavior-changes-12#exported)\n- [Lint Check: Exported PreferenceActivity shouldn't be exported](https://googlesamples.github.io/android-custom-lint-rules/checks/ExportedPreferenceActivity.md.html)\n- [Lint Check: Exported Receiver doesn't require permission](https://googlesamples.github.io/android-custom-lint-rules/checks/ExportedReceiver.md.html)\n- [Lint Check: Exported Service doesn't require permission](https://googlesamples.github.io/android-custom-lint-rules/checks/ExportedService.md.html)"]]