Android安全开发之 Provider 组件安全

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

Android安全开发之 Provider 组件安全

  • 一、安全渗透案例
  • 二、解决方案
    • 2.1 无需 exported
    • 2.2 需要 exported
  • 三、正确的定义私有权限
  • 四、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"

<provider
    android: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 UID 10196
	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",这个时候我们需要添加鉴权校验或包名过滤。

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

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

@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    if (!isAuthorized()) {
        throw new SecurityException("Access denied. Unauthorized.");
    }
    // 返回数据查询
}

private boolean isAuthorized() {
    return AUTHORIZE_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组件可能会被恶意应用利用来执行恶意代码,例如植入病毒、木马等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/696964.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电阻常见失效模式

电阻常见失效模式&#xff1a; 电阻器由于结构较为简单&#xff0c;工艺成熟&#xff0c;通常失效率相对较低。器失效主要表现为以下几种&#xff1a; 阻值漂移&#xff1a;老化后通常发生&#xff1b;&#xff08;通过老化试验进行筛选&#xff0c;规避该问题&#xff09; …

万能表单与AI的完美融合,打造个性化AI小程序

在人工智能技术日益成熟的今天&#xff0c;如何将AI智能与用户界面无缝结合&#xff0c;已成为软件开发领域的新挑战。MyCms 以其创新的“万能表单结合AI”功能&#xff0c;为开发者提供了一个全新的解决方案&#xff0c;让个性化AI小程序的开发变得前所未有的简单和高效。 一、…

OBS 录屏软件:录制圆形头像画中画,设置卡通人像(保姆级教程,有步骤图,建议收藏)

Mac分享吧 文章目录 一、OBS录屏软件 圆形头像画中画效果注意&#xff1a;圆形画中画仅需要在软件中设置一次&#xff0c;每次录制&#xff0c;使用带有圆形头像画中画的场景 录制视频即可。该场景不可删除&#xff01;&#xff01;&#xff01;若删除&#xff0c;则需要重新设…

奇安信停服,国内还有什么可用的高防么?

这里写自定义目录标题 背景DDOS怎么办&#xff1f;方案推荐总结 背景 继前段时间百度云加速通知免费服务&#xff0c;6月底奇安信也将停止服务&#xff0c;到时候国内将几乎不存在免费好用的高防CDN了&#xff1b;类似的事情还有阿里云和腾讯云的一年期免费SSl证书也都停止供应…

day31贪心算法part01| 理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和

**455.分发饼干 ** 视频讲解 | 力扣链接刚开始想到的&#xff0c;但是这样太暴力了&#xff0c;太笨了 class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {// 胃口g 饼干尺寸sint result 0;sort(s.begin(), s.end());…

苍穹外卖笔记-08-套餐管理-增加,删除,修改,查询和起售停售套餐

套餐管理 1 任务2 新增套餐2.1 需求分析和设计接口设计setmeal和setmeal_dish表设计 2.2 代码开发2.2.1 根据分类id查询菜品DishControllerDishServiceDishServiceImplDishMapperDishMapper.xml 2.2.2 新增套餐接口SetmealControllerSetmealServiceSetmealServiceImplSetmealMa…

通过 Webhook 将消息推送至钉钉、飞书、企业微信

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 当我们在 VPS 与 NAS 上部署了大量的应用&#xff0c;如何优雅的接收推送消息就成了一个大问题&#xff0c;在“上古时代”最常用的莫过于 SMTP 直接发送邮件进行通知&#xff0c;但当推送的消息过多且频繁…

《编程小白变大神:DjangoBlog带你飞越代码海洋》

还在为你的博客加载速度慢而烦恼&#xff1f;DjangoBlog性能优化大揭秘&#xff0c;让你的网站速度飞跃提升&#xff01;本文将带你深入了解缓存策略、数据库优化、静态文件处理等关键技术&#xff0c;更有Gunicorn和Nginx的黄金搭档&#xff0c;让你的博客部署如虎添翼。无论你…

认识Spring中的BeanFactoryPostProcessor

先看下AI的介绍 在Spring 5.3.x中&#xff0c;BeanFactoryPostProcessor是一个重要的接口&#xff0c;用于在Spring IoC容器实例化任何bean之前&#xff0c;读取bean的定义&#xff08;配置元数据&#xff09;&#xff0c;并可能对其进行修改。以下是关于BeanFactoryPostProce…

Linux shell编程学习笔记58:cat /proc/mem 获取系统内存信息

0 前言 在开展系统安全检查的过程中&#xff0c;除了收集cpu信息&#xff0c;我们还需要收集内存信息。在Linux中&#xff0c;获取内存信息的命令很多&#xff0c;这里我们着重研究 cat /proc/mem命令。 1 cat /proc/mem命令 /proc/meminfo 文件提供了有关系统内存的使用情况…

每日复盘-20240607

今日关注&#xff1a; 这几天市场环境不好&#xff0c;一直空仓。 六日涨幅最大: ------1--------605258--------- 协和电子 五日涨幅最大: ------1--------605258--------- 协和电子 四日涨幅最大: ------1--------605258--------- 协和电子 三日涨幅最大: ------1--------0…

20240605解决飞凌的OK3588-C的核心板刷机原厂buildroot不能连接ADB的问题

20240605解决飞凌的OK3588-C的核心板刷机原厂buildroot不能连接ADB的问题 2024/6/5 13:53 rootrootrootroot-ThinkBook-16-G5-IRH:~/repo_RK3588_Buildroot20240508$ ./build.sh --help rootrootrootroot-ThinkBook-16-G5-IRH:~/repo_RK3588_Buildroot20240508$ ./build.sh lun…

24.6.9( 概率dp)

星期一&#xff1a; abc356 D atc传送门 思路&#xff1a;按位与操作&#xff0c;M的非零位对答案一定没有贡献&#xff0c;对M为1的位&#xff0c;考虑有多少k此位也为1 按位枚举&#xff0c;m此位为0跳…

require.context()函数介绍

业务需求&#xff1a; 前端Vue项目怎样读取src/assets目录下所有jpg文件 require.context()方法来读取src/assets目录下的所有.jpg文件 <template><div><img v-for"image in images" :src"image" :key"image" /></div> …

一篇文章搞定Java数组初始化,从此告别迷惑

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

Java:集合框架

1.Collection接口 collection接口是Java最基本的集合接口&#xff0c;它定义了一组允许重复的对象。它虽然不能直接创建实例&#xff0c;但是它派生了两个字接口List和Set&#xff0c;可以使用子接口的实现类创建实例。Collection 接口是抽取List接口和Set接口共同的存储特点和…

2024.6.10学习记录

1、代码随想录二刷 2、项目难点 review 3、计组复习

6-Maven的使用

6-Maven的使用 常用maven命令 //常用maven命令 mvn -v //查看版本 mvn archetype:create //创建 Maven 项目 mvn compile //编译源代码 mvn test-compile //编译测试代码 mvn test //运行应用程序中的单元测试 mvn site //生成项目相关信息的网站 mvn package //依据项目生成 …

线程知识点总结

Java线程是Java并发编程中的核心概念之一&#xff0c;它允许程序同时执行多个任务。以下是关于Java线程的一些关键知识点总结&#xff1a; 1. 线程的创建与启动 继承Thread类&#xff1a;创建一个新的类继承Thread类&#xff0c;并重写其run()方法。通过创建该类的实例并调用st…