一、前言
前几篇帖子我们将Android的四大组件中漏洞做了一个具体的介绍,本节我们将进一步介绍Android中的权限配置相关的漏洞以及Android安全配置漏洞,因为权限配置往往和组件关联性很大,所以大家可以结合前几篇帖子来看。2017年权限漏洞仍占据漏洞榜单的第三名,但随着近几年的快速发展,开发人员开始不断注意对权限的安全设置,权限漏洞已经逐渐减少了。
本文第二节主要讲述Android权限机制,以及Android中权限所涉及的安全问题
本文第三节主要讲述权限安全漏洞的原理和拿两个案例复现相关的权限漏洞,并给出了相应的防护方案
本文第四节主要介绍Android中的安全配置问题,梳理了AndroidManifest.xml的结构注册,并讲解了相关的配置安全问题
本文第五节主要复现和详细介绍了Android安全配置中的漏洞问题
二、Android权限机制介绍
1. Android权限
(1)Android权限原理
Android设置权限主要是为了保护Android用户的隐私,根据功能不同,系统会授予不同的权限,而对于用户的一些敏感数据,用户必须要申请权限之后才能访问,具体的示意图如下:
(2)Android权限的分类
从官方的文档中,我们可以知道Android将权限分为:安装时权限、运行时权限和特殊权限
1 |
(1)安装时权限:用户在安装应用程序时,应用程序会向用户申请的基本权限,这类权限一般被分配为:普通权限和签名权限 |
我们从上文中可以知道Android 6.0是一个重要节点,所以下面我们以此为界详细的描述权限的变化情况,权限的API参考:权限API列表
1 |
危险权限的处理: |
1 |
正常权限:manifest文件声明即可使用,安装apk时授予,app运行时不在提示 |
(3)权限组
Android系统对所有的危险权限
进行了分组,称为权限组
权限组 | 权限 |
---|---|
CALENDAR | READ_CALENDAR WRITE_CALENDAR |
CAMERA | CAMERA |
CONTACTS | READ_CONTACTS WRITE_CONTACTS GET_ACCOUNTS |
LOCATION | ACCESS_FINE_LOCATION ACCESS_COARSE_LOCATION |
MICROPHONE | RECORD_AUDIO |
PHONE | READ_PHONE_STATE CALL_PHONE READ_CALL_LOG WRITE_CALL_LOG ADD_VOICEMAIL USE_SIP PROCESS_OUTGOING_CALLS |
SENSORS | BODY_SENSORS |
SMS | SEND_SMS RECEIVE_SMS READ_SMS RECEIVE_WAP_PUSH RECEIVE_MMS |
STORAGE | READ_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE |
1 |
权限组的区别: |
(4)如何请求权限
<1>向清单文件中添加权限
1 |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
无论应用需要什么权限,都需要在清单文件中对权限声明,系统会根据权限的等级来采取不同的操作,对不同的权限,系统会在安装应用时立即授予这些权限,对于危险权限,则需要用户明确授权才能获得
<2>运行时申请权限
申请权限的常用步骤:
1 |
权限申请步骤: |
检查有无权限:
应用程序需要一项危险权限,每次执行需要危险权限的操作时,都必须检查自己是否具有该权限,Android 6.0开始,用户可以1随时从任何应用撤销权限,即便应用以较低的API为目标平台,检查应用是否具备某项权限,调用ContextCompat.checkSelfPermission()
1 |
ContextCompat.checkSelfPermission方法:检查是否具有某项权限 |
申请权限:
1 |
ActivityCompat.requestPermissions方法: |
1 |
(1)requestPermissions执行时会弹系统对话框申请相关的权限。用户可以选择同意授权,或者拒绝授权。对话框关闭之后就走Activity的onRequestPermissionsResult回调了 |
对话框关闭后,请求回调:
1 |
onRequestPermissionsResult方法: |
1 |
回调函数,你授权后就会执行call(),你没有授权就会提示没有权限 |
(5)自定义权限
Android中应用程序可以自定义权限来提供给其他程序访问自己的功能
<1> 如何定义自定义权限
我们要定义自定义权限,需要在AndroidManifest.xml
中使用<permission>
来声明
1 |
<manifest |
1 |
属性说明: |
<2>自定义权限使用
我们先在进程1中定义自定义权限:
1 |
<?xml version="1.0" encoding="utf-8"?> |
然后我们在进程2中声明该自定义权限:
1 |
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
在进程2的MainActivity中编写代码
1 |
Intent intent = new Intent(); |
这样我们就可以顺利从进程2跳转到进程1
<3>自定义权限注意点
1 |
(1)两个应用声明了相同的权限? |
2.权限安全种类和危害
权限漏洞种类:
安全场景:
我们通过上面的分析,可以发现大部分权限安全的场景都发生在保护级别设置不当,自定义权限中如果权限控制不当,往往就会导致各种越权等安全问题的发生。我们再次看一下自定义权限的结构:
1 |
<permission |
1 |
Normal:最低等级,系统会默认授予次权限,不会提示用户,低风险,所以的APP不能访问和共享此APP |
三、权限安全漏洞原理分析和复现
1.漏洞原理
介绍权限漏洞之前,我们先讲解一下Android组件基本知识,前几篇帖子我们也介绍过,Android程序运行在独立的沙箱环境中,相互隔离,为了方便通信,Android提供了组件间的通信(ICC)机制,允许满足条件的组件相互传递数据,ICC的实现依赖于Intent和Binder机制,其底层是通过进程间通信来实现的。在组件的通信过程中,Intent是数据传播的载体,通信发起方发送Intent,携带执行的动作、动作相关的数据和附加数据等信息,通信接收方预先定义自身的Intent-filter,intent-filter中包含能够响应intent的动作和数据类型,声明能够响应的intent请求,应用程序框架在通信发起Intent后,负责找到能处理该Intent的接收方。
组件间通信的一个前提是接收方组件必须公开,Android中的组件分为公开组件和私有组件,具体有export是否可导出决定,而Android权限泄漏漏洞就是由于不合理的公开了组件或者没有对接收的Intent进行合法性校验导致,其表现为将一个拥有权限的API通过公开组件暴露给外界,攻击者可以构造数据访问这个API达到权限提升的效果,一般表现为两个方面:隐私获取和动作执行
1 |
隐私获取:指的是攻击者通过构造数据访问存在权限泄露漏洞的程序组件,并让该组件返回隐私数据,这些数据包括短信消息、联系人信息、地理位置、邮件信息等等 |
具体的示意图如下所示:
应用程序B是一个拥有权限P1的应用程序,包含组件C1,C1组件是公开给外界,意为export = true,并且C1组件可以访问权限P1对应的系统资源,这样另外一个没有权限P1的应用程序A,可以构造Intent数据去启动应用程序B的C1组件,进而访问到P1权限对应的系统资源,拥有权限P1的应用程序B没有对权限合理的保护,引发了权限泄漏,没有权限P1的应用程序A利用这个漏洞获得了权限,导致了权限泄漏
2.漏洞案例
(1)下载文件权限泄漏漏洞
目标程序:
配置文件:
1 |
<!--网络--> |
代码段:
1 |
public class Download extends BroadcastReceiver { |
攻击程序:
1 |
public class MainActivity extends AppCompatActivity { |
效果显示:
测试样例:
攻击样例:
我们可以很明显发现,我们可以通过进程B发送广播到进程A,从而调用进程A的下载功能,开始下载
(2)猎豹清理大师内存清理权限泄漏漏洞
这个案例是一个很早之前的漏洞,现在参考意义不大,不过大家可以借助其学习其原理即可
漏洞描述:
1 |
Android应用程序猎豹清理大师存在自定义的权限android.permission.RESTART_PACKAGES,该权限主要用来结束进程来达到清理内存的目的,当其他没有申请此权限的app向目标程序发送相应的intent时,便可以结束后台运行的部分app进程 |
漏洞实现:
这就是很典型的我们利用个人定义的权限,来攻击目标程序,达到权限泄漏漏洞的目标
3.漏洞防护
(1)组件设置不可导出
我们从上面的两个案例可以发现,Android的权限泄漏漏洞往往和四大组件相互关联,我们对一些重要组件设置不可导出,就可以达到一定的保护效果
(2)设置权限级别
我们可以对自定义的权限一定要设置相应的保护级别,从上文我们可以得出:
1 |
android:protectionLevel="normal",不需要动态申请 |
四、Android默认设置介绍
在上文中已经向大家详细介绍了Android中的权限安全漏洞的情况,接下来我们进一步了解Android中的默认设置以及默认设置引起的安全问题,Android中的默认设置主要分为:AndroidManifest.xml配置文件和WebView的默认设置
(1)AndroidManifest.xml默认设置
这里我总结了AndroidManifest.xml的基本结构图
这里我们主要关注allowBackup、Debuggable、组件默认导出
<1> allowBackup
Android API Level 8及其以上Android系统提供了应用程序的备份和恢复功能,这是由AndroidManifest.xml文件中的allowBackup
属性决定,allowBackup 标志为 true 时,用户即可通过 adb backup
和 adb restore
来进行对应用数据的备份和恢复
Android 属性allowBackup 安全风险源于adb backup容许任何一个人能够打开USB调试开关,从Android手机中复制应用数据到外设,一旦数据被备份之后,所有应用数据都可被用户读取。adb restore
容许用户指定一个恢复的数据来源(即备份的应用数据)来恢复应用程序数据的创建
安全影响:
1 |
通讯录应用,一旦应用程序支持备份和恢复功能,攻击者即可通过 adb backup 和 adb restore 进行恢复新安装的同一个应用来查看聊天记录等信息 |
allowBackup安全风险详情:
1 |
1.allowBackup 风险位置:AndroidMannifest.xml 文件 android:allowBackup 属性 |
数据备份:
1 |
命令:adb backup [-system|nosystem] -all [-apk|-noapk] [-shared|-noshared] -f <档案名称>[需要备份的应用包名] |
例如我们直接备份
1 |
adb backup -apk -shared -system -all -f applock.ab |
就会在电脑默认路径下产生applock.ab文件,大小与系统有关
查看数据:
一般我们使用abe工具来解析ab文件,工具参考网址:abe工具
解压命令:
1 |
java -jar ade.jar unpack 1.ab 1.tar |
恢复数据:
1 |
adb restore applock.ab |
<2> debuggable
android:debuggable
属性是指定应用程序是否能够被调试,即时是以用户模式运行在设备上的时候,如果设置为 true ,则能够被调试,否则不能调试,默认值是false
逆向工作人员在对一个apk程序进行逆向时,第一步往往就是要对debuggable属性进行绕过,否则就不能进行正常的调试,因此如果属性本身设为true,更容易导致该应用存在动态调试,泄露数据信息的风险
<3> exported
前几篇帖子,我们讲述四大组件过程中,经常会涉及到exported导出导致的漏洞,exported组件导出,会导致导出的组件被第三方APP任意调用,导致敏感信息,并可能受到绕过认证、恶意代码注入等风险,由于前面我们已经讲得很详细了,这里就不再做过多描述
(2)WebView默认设置
WebView是android中用来展示网页的重要控件,Android中经常会使用WebView来实现Web页面的展示,在Activity中启动自己的浏览器或者简单的展示一些在线内容等,而WebView上的漏洞问题也各种各样,过去几年内WebView中被披露的重大漏洞包括了任意代码执行漏洞、跨域、密码明文保存等,后面我们将WebView作为一个专题讲述上面存在的漏洞问题,这里我们只关注WebView中默认设置的安全问题
后面我们主要讲述WebView上几方面的默认设置漏洞
五、Android默认设置漏洞原理分析和复现
1. allowBackup
(1)备份安全设置信息泄露漏洞
上文我们已经详细的给大家讲述了allowBackup
设置true
的安全性,接下来我拿一个案例带大家深入了解:
<1> 漏洞复现
样本:sieve.apk
信息设置:
首先,我们将样本安装到手机上,并打开主界面
进入主程序我们发现,提示我们注册密码,而且需要至少16位,这里我们输入密码zxcvbnm0123456789
进入后,又要我们输入PIN码,我们输入1234
然后我们发现需要再次输入密码才能进入,我们再次输入密码
发现右上角可以添加账户密码信息,我们添加,密码设置123456
这样我们就在apk中就存入了一些信息,接下来我们来看如何备份和恢复这些信息呢
数据备份:
我们先用jadx-gui打开目标程序,查看allowbackup=true
这里发现是可以备份的,所以我们输入备份命令
1 |
adb backup -f allowBackup.ab -noapk com.mwr.example.sieve |
我们的手机就弹出备份请求,如果你要加密就输入加密密码,这里我们直接备份
备份完成后,我们在当前目录下就可以发现我们备份的文件allowBackup.ab
数据解析:
我们需要使用abe
工具对备份的文件解压,下载路径:abe工具
我们下载后,需要安装jdk环境,然后使用命令解压:
1 |
java -jar abe.jar unpack allowBackup.ab 1.tar |
解压
我们就得到了database.db数据库,然后我们使用DB Browser for SQLite打开,下载路径:DB Browser
这样我们就成功解析出了备份的数据信息
数据恢复:
我们卸载目标程序,然后重新安装
我们输入恢复命令:
1 |
adb restore allowBackup.ab |
然后我们恢复数据,数据恢复完成
我们再次进入发现,直接进入之前界面,说明此时我们输入之前密码,就可以成功的进入
登录成功,并且出现我们之前的密码信息
<2> 漏洞说明
上文我们拿一个样例,带大家完整的复现了一遍数据备份漏洞的过程,这个过程中如果我们发现一个目标程序的allowBackup
为true,我们可以备份下其数据信息,在另外一个安装该目标程序的手机中进行恢复,这样我们就可以获得用户的敏感数据信息了,另外一个类似的案例可以参考网址:阿里聚安全allowBackup安全解析
<3> 安全防护
只需要将allowBackup设置为false即可
(2)debuggable 安全风险
我们知道debuggable=true
,用户才能进行动态调试,下面就是debuggable=false
,使用AndroidStudio调试的情况
下面我们介绍几种方法绕过debuggle=false
<1> 使用mprop
mprop下载地址:mprop
原理解析:
1 |
通过修改 ro.debuggable =1 来达到调试的目的,由于不是从系统内核层面修改,所以系统重启之后需要重新配置 |
配置过程:
首先, 将mprop文件拷贝到./data/local/tmp文件下
1 |
adb push mprop /data/local/tmp |
然后运行
1 |
./mprop ro.debuggable 1 |
查询是否修改成功:
1 |
getprop ro.debuggable |
我们修改值后,还需要重启一下,使得进程被更新,使用命令
1 |
stop;start |
此时我们就可以进行动态调试了
<2> 使用Xposed模块
xposed模块中很多都可以通过hook来修改 ro.debuggable
的值,这里我们使用App Debuggable
模块,下载地址
使用过程十分简单,我们的手机上安装Xposed框架之后,我们只需要将模块安装上去,激活即可,Xposed框架安装详细看之前帖子
<3> 系统定制
我们也可以通过定制系统源码的方式来实现绕过,这里考虑到文章篇幅的原因,这里我收集了一个大佬的方法,相关教程我会放到github上,大家自行参考
(3)exported导出漏洞
由于exported导出漏洞基本是和Android四大组件相关,我们在前面的帖子中已经将这里讲的比较详细了,大家可以回看前面的帖子
安全防护:
1 |
(1)权限控制 |
具体参考上文和前面帖子
2. WebView安全配置漏洞
由于WebView涉及的漏洞较多,后面我会做一个专题归纳WebView的大部分漏洞的情况,这里只是简要列出一些配置相关的漏洞问题
(1)漏洞原理
webview控件将setAllowFileAccessFromFileURLs
或setAllowUniversalAcessFromFileURLsAPI
设置为true
,开启了file域访问,且允许file域访问HTTP域,但是并未对file域的路径做严格限制
检测方法:
1 |
webview控件是否将setAllowFileAccessFromFileURLs或setAllowUniversalAcessFromFileURLsAPI设置为true |
(2)漏洞案例
<1> WebView密码明文存储漏洞——setSavePassword(true)
WebView默认开启密码保存功能 mWebView.setSavePassword(true),如果该功能未关闭,在用户输入密码时,会弹出提示框,询问用户是否保存密码,如果用户确定,密码会被保存在/data/data/com.package.name/databases/webview.db
,然后我们可以在root权限下直接拿出密码相关信息,因此建议用户密码加密存储
<2> WebView域控制不严格漏洞
setAllowFileAccess
WebView默认开启密码保存功能 mWebView.setAllowFileAccess(true) ,在File域下,能够执行任意的JavaScript代码,同源策略跨域访问能够对私有目录文件进行访问,APP对切入WebView未对file:///形式的URL做限制,会导致隐私信息泄漏,针对聊天软件会导致信息泄漏,针对浏览器软件,会导致cookie信息泄漏
setAllowFileAccessFromFileURLs
在JELLY_BEAN以前的版本默认是setAllowFileAccessFromFileURLs(true),允许通过file域url中的Javascript读取其他本地文件,在JELLY_BEAN及以后的版本中默认已被是禁止。
setAllowUniversalAccessFromFileURLs
在JELLY_BEAN以前的版本默认是setAllowUniversalAccessFromFileURLs(true),允许通过file域url中的Javascript访问其他的源,包括其他的本地文件和http,https源的数据。在JELLY_BEAN及以后的版本中默认已被禁止。
案例:360手机浏览器缺陷可导致用户敏感数据泄漏
以360手机浏览器4.8版本为例,由于未对file域做安全限制,恶意APP调用360浏览器加载本地的攻击页面(比如恶意APP释放到SDCARD上的一个HTML)后,就可以获取360手机浏览器下的所有私有数据,包括webviewCookiesChromium.db下的cookie内容
攻击页面关键代码
1 |
function getDatabase() { |
漏洞利用代码:
1 |
copyFile(); //自定义函数,释放filehehe.html到sd卡上 |
(3)安全防护
通过以下设置,防止越权访问,跨域等安全问题
1 |
(1)将不必要导出的组件设置为不导出 |
六、实验总结
本文总结归纳了Android中的权限安全漏洞和安全配置漏洞的详细信息,并拿一些案例进行了复现讲解,本文中只是对大部分这些漏洞的一个归纳总结,里面存在的一些问题就请各位指正了,本文所用到的实验样例和相关附件,后面都会上传github,详细大家参考:github地址
七、参考文献
1 |
第一行代码 |
- source:security-kitchen.com
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论