0


Android安全开发之 Provider 组件安全

Android系统中的Content Provider组件是一种用于在不同应用之间共享数据的机制。它提供了一种安全、可控的方式,允许应用访问其他应用的数据。然而,如果Provider组件的安全措施没有得到妥善实现,则可能会导致严重的安全漏洞,例如数据泄露、隐私侵犯甚至恶意代码执行。

Android安全开发之 Provider 组件安全

一、安全渗透案例

测试步骤:

1.进入应用进行添加新内容,插入数据库

2.使用adb或者编写apk,对指定uri进行查询

1.adb shell content query --uri content://com.xxx.note.data.NoteProvider/note

测试结论:

编辑内容都会通过uri查询出来,泄露用户隐私信息,未鉴权

server@dev-fj-srv:~/Desktop $ adb shell content query --uri content://com.xxx.note.data.NoteProvider/note
Row: 0_id=1, title=, content=<?xml version="1.0"encoding="UTF-8"?><note><notetxt>地址</notetxt></note>, longdate=1717745973845, iscollect=0, iscontainpic=0, isprivate=0, isdeleted=0, backgroundid=4, parentfolderid=-10, istop=0, topdate=0, iscontainvoice=0, picpath=NULL
Row: 1_id=2, title=, content=<?xml version="1.0"encoding="UTF-8"?><note><notetxt>账户</notetxt></note>, longdate=1717745961274, iscollect=0, iscontainpic=0, isprivate=0, isdeleted=0, backgroundid=4, parentfolderid=-10, istop=0, topdate=0, iscontainvoice=0, picpath=NULL
Row: 2_id=3, title=, content=<?xml version="1.0"encoding="UTF-8"?><note><notetxt>密码</notetxt></note>, longdate=1717745951538, iscollect=0, iscontainpic=0, isprivate=0, isdeleted=0, backgroundid=4, parentfolderid=-10, istop=0, topdate=0, iscontainvoice=0, picpath=NULL

漏洞修复建议:

增加鉴权校验

很多人可能会好奇,我的代码进行了混淆处理,如何发现我的

provider

及其

authorities

,可以通过APK文件进行逆向或反编译出

AndroidManifest.xml

,此类声明信息是不会被混淆的,可以直接获取的。

甚至可以直接通过adb获取:

adb dumpsys package com.xxx.note

直接获取得到

ContentProvider Authorities
ContentProvider Authorities:
  [com.xxx.note.data.SearchProvider]:
    Provider{fc33540 com.xxx.note/.data.SearchProvider}applicationInfo=ApplicationInfo{5ba67a5 com.xxx.note}[com.xxx.note.provider]:
    Provider{19d68c3 com.xxx.note/androidx.core.content.FileProvider}applicationInfo=ApplicationInfo{a90977a com.xxx.note}[com.xxx.note.data.NoteProvider]:
    Provider{da7fc72 com.xxx.note/.data.NoteProvider}applicationInfo=ApplicationInfo{13db2b com.xxx.note}

二、解决方案

2.1 无需 exported

当 ContentProvider 仅应用自身使用,无需 exported 供其他应用调用,即可直接设置

exported="false"
<providerandroid:name=".data.NoteProvider"android:authorities="com.xxx.note.data.NoteProvider"android:exported="false"/>

此时再通过 adb 命令查询就会出现

SecurityException

报错无法查询

server@dev-fj-srv:~/Desktop$ adb shell content query --uri content://com.xxx.note.data.NoteProvider/note
Error while accessing provider:com.xxx.note.data.NoteProvider
java.lang.SecurityException: Permission Denial: opening provider com.xxx.note.data.NoteProvider from (null)(pid=10781, uid=2000) that is not exported from UID10196
    at android.os.Parcel.createExceptionOrNull(Parcel.java:3057)
    at android.os.Parcel.createException(Parcel.java:3041)
    at android.os.Parcel.readException(Parcel.java:3024)
    at android.os.Parcel.readException(Parcel.java:2966)
    at android.app.IActivityManager$Stub$Proxy.getContentProviderExternal(IActivityManager.java:7803)
    at com.android.commands.content.Content$Command.execute(Content.java:516)
    at com.android.commands.content.Content.main(Content.java:735)
    at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
    at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:447)
Caused by: android.os.RemoteException: Remote stack trace:
    at com.android.server.am.ContentProviderHelper.checkAssociationAndPermissionLocked(ContentProviderHelper.java:756)
    at com.android.server.am.ContentProviderHelper.getContentProviderImpl(ContentProviderHelper.java:411)
    at com.android.server.am.ContentProviderHelper.getContentProviderExternalUnchecked(ContentProviderHelper.java:182)
    at com.android.server.am.ContentProviderHelper.getContentProviderExternal(ContentProviderHelper.java:176)
    at com.android.server.am.ActivityManagerService.getContentProviderExternal(ActivityManagerService.java:6889)

2.2 需要 exported

当 ContentProvider 需要通过数据接口供其他应用使用时,就只能设置

exported="true"

,这个时候我们需要添加鉴权校验或包名过滤。

<providerandroid:name=".data.SearchProvider"android:authorities="com.xxx.note.data.SearchProvider"android:exported="true"/>

在重写 ContentProvider query 方法时先进行校验,验证成功后再返回查询数据。

@OverridepublicCursorquery(Uri uri,String[] projection,String selection,String[] selectionArgs,String sortOrder){if(!isAuthorized()){thrownewSecurityException("Access denied. Unauthorized.");}// 返回数据查询}privatebooleanisAuthorized(){returnAUTHORIZE_ACCESS_PACKAGE.equals(getCallingPackage());}
AUTHORIZE_ACCESS_PACKAGE

即为允许访问此 ContentProvider 的应用包名。

此时再通过 adb 命令访问此 ContentProvider 就会返回

java.lang.SecurityException: Access denied. Unauthorized.

报错。通过 adb 访问时候可以查询到 getCallingPackage() 为

com.android.shell

,不在我们运行访问的包名名单内。

server@dev-fj-srv:~/Desktop$ adb shell content query --uri content://com.xxx.note.data.SearchProvider
Error while accessing provider:com.xxx.note.data.SearchProvider
java.lang.SecurityException: Access denied. Unauthorized.
    at android.os.Parcel.createExceptionOrNull(Parcel.java:3057)
    at android.os.Parcel.createException(Parcel.java:3041)
    at android.os.Parcel.readException(Parcel.java:3024)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:190)
    at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:142)
    at android.content.ContentProviderProxy.query(ContentProviderNative.java:495)
    at com.android.commands.content.Content$QueryCommand.onExecute(Content.java:661)
    at com.android.commands.content.Content$Command.execute(Content.java:522)
    at com.android.commands.content.Content.main(Content.java:735)
    at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
    at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:447)

三、正确的定义私有权限

在AndroidManifest中定义私有权限的语法为:
img

其中

android:protectionLevel

的可选值分别表示:

  • normal:默认值,低风险权限,在安装的时候,系统会自动授予权限给 application。
  • dangerous:高风险权限,如发短信,打电话,读写通讯录。使用此protectionLevel来标识用户可能关注的一些权限。Android将会在安装程序时,警示用户关于这些权限的需求,具体的行为可能依据Android版本或者所安装的移动设备而有所变化。
  • signature: 签名权限,在其他 app 引用声明的权限的时候,需要保证两个 app 的签名一致。这样系统就会自动授予权限给第三方 app,而不提示给用户。
  • signatureOrSystem:除了具有相同签名的APP可以访问外,Android系统中的程序有权限访问。

大部分开放的Provider,是提供给本公司的其他应用使用的,一般的话一个公司打包签名APP的签名证书都应该是一致的,这种情况下,Provider的

android:protectionLevel

应为设为“

signature

”。

四、Provider 组件的安全风险

  1. 权限控制不当:如果Provider组件没有正确配置权限,则可能会允许未经授权的应用访问敏感数据。
  2. 数据泄露:Provider组件可能会被恶意应用利用来窃取敏感数据,例如联系人信息、通话记录、短信内容等。
  3. 隐私侵犯:Provider组件可能会被恶意应用利用来跟踪用户行为,例如位置信息、浏览历史等。
  4. 恶意代码执行:Provider组件可能会被恶意应用利用来执行恶意代码,例如植入病毒、木马等。
标签: android 安全 Provider

本文转载自: https://blog.csdn.net/weixin_44008788/article/details/139527894
版权归原作者 Just_Paranoid 所有, 如有侵权,请联系我们删除。

“Android安全开发之 Provider 组件安全”的评论:

还没有评论