Ejemplo n.º 1
0
 def do_detect(self):
     with self.context.store() as store:
         for cl in store.query().invocations(
                 InvocationPattern(
                     'invoke-',
                     'L.*->([dwie]|debug|error|exception|warning|info|notice|wtf)\(Ljava/lang/String;Ljava/lang/String;.*?Ljava/lang/(Throwable|.*?Exception);|L.*;->print(ln)?\(Ljava/lang/String;|LException;->printStackTrace\('
                 )):
             if 'print' not in cl.p[1].v:
                 try:
                     yield Issue(
                         detector_id=self.option,
                         confidence=IssueConfidence.TENTATIVE,
                         cvss3_vector=self.cvss,
                         summary='detected logging',
                         info1=cl.p[1].v,
                         info2=DataFlows.solved_constant_data_in_invocation(
                             store, cl, 1),
                         source=store.query().qualname_of(cl))
                 except (DataFlows.NoSuchValueError):
                     yield Issue(detector_id=self.option,
                                 confidence=IssueConfidence.TENTATIVE,
                                 cvss3_vector=self.cvss,
                                 summary='detected logging',
                                 info1=cl.p[1].v,
                                 source=store.query().qualname_of(cl))
             elif 'Exception;->' not in cl.p[1].v:
                 try:
                     yield Issue(
                         detector_id=self.option,
                         confidence=IssueConfidence.TENTATIVE,
                         cvss3_vector=self.cvss,
                         summary='detected logging',
                         info1=cl.p[1].v,
                         info2=DataFlows.solved_constant_data_in_invocation(
                             store, cl, 0),
                         source=store.query().qualname_of(cl))
                 except (DataFlows.NoSuchValueError):
                     yield Issue(detector_id=self.option,
                                 confidence=IssueConfidence.TENTATIVE,
                                 cvss3_vector=self.cvss,
                                 summary='detected logging',
                                 info1=cl.p[1].v,
                                 source=store.query().qualname_of(cl))
             else:
                 yield Issue(detector_id=self.option,
                             confidence=IssueConfidence.TENTATIVE,
                             cvss3_vector=self.cvss,
                             summary='detected logging',
                             info1=cl.p[1].v,
                             source=store.query().qualname_of(cl))
Ejemplo n.º 2
0
 def analyzed(self, store: Store, op: Op) -> Optional[str]:
     x = op.p[1].v
     if re.search(
             'Landroid/provider/Settings\$Secure;->getString\(Landroid/content/ContentResolver;Ljava/lang/String;\)Ljava/lang/String;',
             x):
         try:
             if DataFlows.solved_constant_data_in_invocation(
                     store, op, 1) == 'android_id':
                 return 'ANDROID_ID'
             else:
                 return None
         except DataFlows.NoSuchValueError:
             return None
     elif re.search(
             'Landroid/telephony/TelephonyManager;->getDeviceId\(\)Ljava/lang/String;',
             x):
         return 'IMEI'
     elif re.search(
             'Landroid/telephony/TelephonyManager;->getSubscriberId\(\)Ljava/lang/String;',
             x):
         return 'IMSI'
     elif re.search(
             'Landroid/telephony/TelephonyManager;->getLine1Number\(\)Ljava/lang/String;',
             x):
         return 'phone number'
     elif re.search(
             'Landroid/bluetooth/BluetoothAdapter;->getAddress\(\)Ljava/lang/String;',
             x):
         return 'L2 address (Bluetooth)'
     elif re.search(
             'Landroid/net/wifi/WifiInfo;->getMacAddress\(\)Ljava/lang/String;|Ljava/net/NetworkInterface;->getHardwareAddress\(\)',
             x):
         return 'L2 address (Wi-Fi)'
     return None
Ejemplo n.º 3
0
    def do_detect(self):
        with self.context.store() as store:
            targets = {'WebView', 'XWalkView', 'GeckoView'}

            more = True
            while more:
                more = False
                for cl in store.query().related_classes('|'.join(targets)):
                    name = store.query().class_name_of(cl)
                    if name not in targets:
                        targets.add(name)
                        more = True

            for fn in (n for n in self.context.disassembled_resources()
                       if 'layout' in n):
                with open(fn, 'rb') as f:
                    r = ET.parse(f,
                                 parser=ET.XMLParser(recover=True)).getroot()
                    for t in functools.reduce(
                            lambda x, y: x + y,
                        (r.xpath('//%s' %
                                 self.context.class_name_of_dalvik_class_type(
                                     c).replace('$', '_')) for c in targets)):
                        size = LayoutSizeGuesser().guessed_size(t, fn)
                        if size > 0.5:
                            try:
                                yield Issue(
                                    detector_id=self.option,
                                    confidence=IssueConfidence.TENTATIVE,
                                    cvss3_vector=self.cvss1,
                                    summary='tamperable webview',
                                    info1='{0} (score: {1:.02f})'.format(
                                        t.attrib['{0}id'.format(
                                            self.xmlns_android)], size),
                                    source=self.context.
                                    source_name_of_disassembled_resource(fn))
                            except KeyError as e:
                                log.warning(
                                    'SecurityTamperableWebViewDetector.do_detect: missing key {0}'
                                    .format(e))

            # XXX: crude detection
            for op in store.query().invocations(
                    InvocationPattern('invoke-', ';->loadUrl')):
                try:
                    v = DataFlows.solved_constant_data_in_invocation(
                        store, op, 0)
                    if v.startswith('http://'):
                        yield Issue(detector_id=self.option,
                                    confidence=IssueConfidence.FIRM,
                                    cvss3_vector=self.cvss2,
                                    summary='tamperable webview with URL',
                                    info1=v,
                                    source=store.query().qualname_of(op))
                except DataFlows.NoSuchValueError:
                    pass
Ejemplo n.º 4
0
    def detect(self) -> Iterable[Issue]:
        import lxml.etree as ET
        from functools import reduce
        with self._context.store() as store:
            targets = {'WebView', 'XWalkView', 'GeckoView'}

            more = True
            while more:
                more = False
                for cl in store.query().related_classes('|'.join(targets)):
                    name = store.query().class_name_of(cl)
                    if name is not None and name not in targets:
                        targets.add(name)
                        more = True

            for fn in (n for n in self._context.disassembled_resources()
                       if 'layout' in n):
                with open(fn, 'rb') as f:
                    r = ET.parse(f,
                                 parser=ET.XMLParser(recover=True)).getroot()
                    for t in reduce(lambda x, y: x + y, (r.xpath('//{}'.format(
                            self._context.class_name_of_dalvik_class_type(
                                c).replace('$', '_'))) for c in targets)):
                        size = LayoutSizeGuesser().guessed_size(t, fn)
                        if size > 0.5:
                            try:
                                yield Issue(
                                    detector_id=self.option,
                                    confidence='tentative',
                                    cvss3_vector=self._cvss1,
                                    summary=self._summary1,
                                    info1='{0} (score: {1:.02f})'.format(
                                        t.attrib[f'{self._xmlns_android}id'],
                                        size),
                                    source=self._context.
                                    source_name_of_disassembled_resource(fn))
                            except KeyError as e:
                                ui.warn(
                                    f'SecurityTamperableWebViewDetector.do_detect: missing key {e}'
                                )

            # XXX: crude detection
            for op in store.query().invocations(
                    InvocationPattern('invoke-', ';->loadUrl')):
                try:
                    v = DataFlows.solved_constant_data_in_invocation(
                        store, op, 0)
                    if v.startswith('http://'):
                        yield Issue(detector_id=self.option,
                                    confidence='firm',
                                    cvss3_vector=self._cvss2,
                                    summary=self._summary2,
                                    info1=v,
                                    source=store.query().qualname_of(op))
                except DataFlows.NoSuchValueError:
                    pass
Ejemplo n.º 5
0
    def detect(self) -> Iterable[Issue]:
        with self._context.store() as store:
            for op in store.query().invocations(
                    InvocationPattern(
                        'invoke-',
                        'Landroid/net/Uri;->parse\(Ljava/lang/String;\)Landroid/net/Uri;'
                    )):
                try:
                    if DataFlows.solved_constant_data_in_invocation(
                            store, op, 0).startswith('content://sms/'):
                        yield Issue(detector_id=self.option,
                                    confidence='certain',
                                    cvss3_vector=self._cvss,
                                    summary=self._summary,
                                    info1='accessing SMS',
                                    source=store.query().qualname_of(op))
                except DataFlows.NoSuchValueError:
                    pass

            for op in store.query().invocations(
                    InvocationPattern('invoke-',
                                      'Landroid/telephony/SmsManager;->send')):
                yield Issue(detector_id=self.option,
                            confidence='certain',
                            cvss3_vector=self._cvss,
                            summary=self._summary,
                            info1='sending SMS',
                            source=store.query().qualname_of(op))

            for op in store.query().invocations(
                    InvocationPattern(
                        'invoke-',
                        'Landroid/telephony/SmsMessage;->createFromPdu\(')):
                yield Issue(detector_id=self.option,
                            confidence='firm',
                            cvss3_vector=self._cvss,
                            summary=self._summary,
                            info1='intercepting incoming SMS',
                            source=store.query().qualname_of(op))
Ejemplo n.º 6
0
 def do_detect(self):
     with self.context.store() as store:
         for cl in store.query().invocations(
                 InvocationPattern(
                     'invoke-virtual',
                     'Landroid/content/Context;->openFileOutput\(Ljava/lang/String;I\)'
                 )):
             try:
                 target_val = int(
                     DataFlows.solved_constant_data_in_invocation(
                         store, cl, 1), 16)
                 if target_val & 3:
                     yield Issue(detector_id=self.option,
                                 confidence=IssueConfidence.CERTAIN,
                                 cvss3_vector=self.cvss,
                                 summary='insecure file permission',
                                 info1={
                                     1: 'MODE_WORLD_READABLE',
                                     2: 'MODE_WORLD_WRITEABLE'
                                 }[target_val],
                                 source=store.query().qualname_of(cl))
             except (DataFlows.NoSuchValueError):
                 pass
Ejemplo n.º 7
0
    def do_detect(self):
        with self.context.store() as store:
            targets = set()
            seeds = {'WebView', 'XWalkView', 'GeckoView'}

            more = True
            while more:
                more = False
                for cl in store.query().related_classes('|'.join(seeds)):
                    name = store.query().class_name_of(cl)
                    if name not in targets:
                        targets.add(name)
                        more = True
            for seed in seeds:
                targets.add('L.*%s;' % seed)

            # XXX: Crude detection
            # https://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface(java.lang.Object,%2520java.lang.String)
            if self.context.get_min_sdk_version() <= 16:
                for p in store.query().invocations(
                        InvocationPattern(
                            'invoke-virtual',
                            'Landroid/webkit/WebSettings;->setJavaScriptEnabled'
                        )):
                    try:
                        if DataFlows.solved_constant_data_in_invocation(
                                store, p, 0):
                            for target in targets:
                                for q in store.query().invocations_in_class(
                                        p,
                                        InvocationPattern(
                                            'invoke-virtual',
                                            '%s->addJavascriptInterface' %
                                            target)):
                                    try:
                                        if DataFlows.solved_constant_data_in_invocation(
                                                store, q, 0):
                                            yield Issue(
                                                detector_id=self.option,
                                                confidence=IssueConfidence.
                                                FIRM,
                                                cvss3_vector=self.cvss,
                                                summary=
                                                'insecure Javascript interface',
                                                source=store.query(
                                                ).qualname_of(q))
                                    except (DataFlows.NoSuchValueError):
                                        yield Issue(
                                            detector_id=self.option,
                                            confidence=IssueConfidence.
                                            TENTATIVE,
                                            cvss3_vector=self.cvss,
                                            summary=
                                            'insecure Javascript interface',
                                            source=store.query().qualname_of(
                                                q))
                    except (DataFlows.NoSuchValueError):
                        pass

                # https://developer.android.com/reference/android/webkit/WebSettings#setMixedContentMode(int)
                if self.context.get_min_sdk_version() <= 20:
                    for q in store.query().invocations_in_class(
                            p,
                            InvocationPattern(
                                'invoke-virtual',
                                'Landroid/webkit/WebSettings;->setMixedContentMode'
                            )):
                        try:
                            val = int(
                                DataFlows.solved_constant_data_in_invocation(
                                    store, q, 0), 16)
                            if val == 0:
                                yield Issue(
                                    detector_id=self.option,
                                    confidence=IssueConfidence.FIRM,
                                    cvss3_vector=self.cvss,
                                    summary='insecure mixed content mode',
                                    info1='MIXED_CONTENT_ALWAYS_ALLOW',
                                    source=store.query().qualname_of(q))
                        except (DataFlows.NoSuchValueError):
                            pass