时时勤拂拭,勿使惹尘埃

TOC

Categories

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 评论:

发表评论