Android(五)Intent Fuzzing on Drozer
Android四大组件
Android四大组件最常见的问题是未导出组件,通常可能导致恶意调用、任意虚假消息的通知、远程代码执行等,其中:
- activity
- 风险描述
- Activity组件的属性exported被设置为true或是未设置exported值但IntentFilter不为空时,activity被认为是导出的,可通过设置相应的Intent唤起activity。
- 危害描述
- 可能构造恶意数据针对导出activity组件实施越权攻击。
- 修复建议
- 如果组件不需要与其他app共享数据或交互,请将AndroidManifest.xml 配置文件中设置该组件为exported = “False”。如果组件需要与其他app共享数据或交互, 请对组件进行权限控制和参数校验。
- 参考链接
- broadcast receivers
- 风险描述
- BroadcastReceiver组件的属性exported被设置为true或是未设置exported值但IntentFilter不为空时,BroadcastReceiver被认为是导出的。
- 危害描述
- 导出的广播可以导致数据泄漏或者是越权。
- 修复建议
- 如果组件不需要与其他app共享数据或交互,请将AndroidManifest.xml 配置文件中设置该组件为exported = “False”。如果组件需要与其他app共享数据或交互, 请对组件进行权限控制和参数校验。
- 参考链接
- content providers
- 风险描述
- Content Provider组件的属性exported被设置为true或是Android API<=16时,Content Provider被认为是导出的。
- 危害描述
- 可能访问到应用本身不想共享的数据或文件。
- 数据泄漏、sql注入、文件遍历
- 修复建议
- 如果组件不需要与其他app共享数据或交互,请将AndroidManifest.xml 配置文件中设置该组件为exported = “False”。如果组件需要与其他app共享数据或交互, 请对组件进行权限控制和参数校验。
- 参考链接
- services
- 风险描述
- Service组件的属性exported被设置为true或是未设置exported值但IntentFilter不为空时,Service被认为是导出的,可通过设置相应的Intent唤起Service。
- 危害描述
- 可能构造恶意数据针对导出Service组件实施越权攻击。
- 修复建议
- 如果组件不需要与其他app共享数据或交互,请将AndroidManifest.xml 配置文件中设置该组件为exported = “False”。如果组件需要与其他app共享数据或交互, 请对组件进行权限控制和参数校验。
- 参考链接
其中拒绝服务主要为Android APP 中暴露的组件,对Intent.getXXXExtra()获取的异常或者畸形数据处理时没有进行异常捕获。而权限提升其实和拒绝服务很类似,只不过目的变成构造更为完整、更能满足程序逻辑的intent。由于activity一般多于用户交互有关,所以基于intent的权限提升更多针对broadcast receiver和service。
Drozer使用
寻找app中相关缺陷,可以使用Intent fuzzing等工具,如IntentFuzzer ,这里结合Drozer,同样也可以在Drozer上自定义的进行intent fuzzing。
以下为drozer相关使用:
- 寻找攻击面
- run app.package.attacksurface com.*
- 获取activity详情
- run app.activity.info -a com.*
- 空intent启动activity
- run app.activity.start —component 包名 包名.类名启动Activity
- 获取broadcast详情
- run app.broadcast.info -a com.run
- 给broadcast发送空intent
- app.broadcast.send —component com..BroadcastReceiver
- 获取service详情
- run app.service.info -a com.mwr.example.sieve
- service权限提升
- run app.service.start —action com.test.vulnerability.SEND_SMS —extra string dest 11111 —extra string text 1111 —extra string OP SEND_SMS
drozer的module开发可以参考实战Drozer模块编写,这里先构造intent格式:
def attack(self,component,package,flags):
act=None
cat=None
data=None
comp=(package,component.name)
extr=None
flgs=None
if(flags=='activity'):
flgs =['ACTIVITY_NEW_TASK']
intent = android.Intent(action=act,component=comp,category=cat,data_uri=None, extras=extr, flags=flgs, mimetype=None)
if intent.isValid():
if(flags=='activity'):
self.getContext().startActivity(intent.buildIn(self))
if(flags=='service'):
self.getContext().startService(intent.buildIn(self))
if(flags == 'receiver'):
self.getContext().sendBroadcast(intent.buildIn(self))
else:
self.stderr.write("[-] Invalid Intent!\n")
初步以空intent为例,给所有app的未导出组件发送空intent,同时可以监控logcat,如程序对Intent.getXXXExtra()获取的空数据处理时没有进行异常捕获,则app会直接crash,然后可以进一步挖掘是否可以权限提升等其他攻击
def execute(self, arguments):
if arguments.package != None:
package = self.packageManager().getPackageInfo(arguments.package, common.PackageManager.GET_ACTIVITIES | common.PackageManager.GET_RECEIVERS | common.PackageManager.GET_PROVIDERS | common.PackageManager.GET_SERVICES)
application = package.applicationInfo
activities = self.match_filter(package.activities, 'exported', True)
receivers = self.match_filter(package.receivers, 'exported', True)
providers = self.match_filter(package.providers, 'exported', True)
services = self.match_filter(package.services, 'exported', True)
attack_actions = []
self.stdout.write("Attack Surface:\n")
self.stdout.write(" %d activities exported\n" % len(activities))
self.stdout.write(" %d broadcast receivers exported\n" % len(receivers))
self.stdout.write(" %d content providers exported\n" % len(providers))
self.stdout.write(" %d services exported\n" % len(services))
if (application.flags & application.FLAG_DEBUGGABLE) != 0:
self.stdout.write(" is debuggable\n")
if package.sharedUserId != None:
self.stdout.write(" Shared UID (%s)\n" % package.sharedUserId)
actions=[activities,receivers,services]
action_str=['activity','receiver','service']
i=-1
try:
for action in actions:
self.stdout.write("[color yellow] ================== empty action test ===============[/color]\n")
i+=1
if len(action) > 0:
for tmp in action:
try:
if len(tmp.name) > 0:
self.stdout.write("[color green] [+]%s name:%s[/color]\n" % (action_str[i],tmp.name))
self.attack(component=tmp, package=arguments.package, flags=action_str[i])
except Exception, e:
self.stdout.write(" [color blue] error-->%s name:%s[/color]\n" % (action_str,tmp.name))
self.stdout.write(" [color blue] errorcontent:%s[/color]\n" % e)
continue
except:
self.stdout.write(" error")
self.stdout.write(" [color blue]activity has no action[/color]\n")
if len(attack_actions) > 0:
self.stdout.write("[color yellow] ============ empty activity test ================ [/color]\n")
for attack_action in attack_actions:
try:
self.stdout.write(" [color green][+]action name: %s[/color]\n" % (attack_action))
intent = self.new("android.content.intent")
intent.setAction(attack_action)
intent.setFlags(0x10000000)
self.getContext().startActivity(intent)
except Exception:
self.stdout.write(" [color blue]action %s start failure...[/color]\n" % (attack_action))
else:
self.stdout.write(" [color blue]activity has no action[/color]\n")
else:
self.stdout.write("No package specified\n")
后续还可以添加intent权限构造、反馈跟踪等功能
0 评论:
发表评论