예제 #1
0
    def target(self, queue):
        files = common.java_files
        global parser, tree, filepath
        parser = plyj.Parser()
        tree = ''
        res = []
        count = 0
        for f in files:
            count += 1
            pub.sendMessage('progress', bar=self.name, percent=round(count * 100 / len(files)))
            filepath = str(f)
            try:
                # Parse the java file to an AST
                tree = parser.parse_file(f)
            except Exception as e:
                common.logger.exception("Unable to parse the file and generate as AST. Error: " + str(e))
                continue

            try:
                for import_decl in tree.import_declarations:
                    # Check if DexClassLoader is called in the import statement; example import dalvik.system.DexClassLoader
                    if self.DEX_CLASS_LOADER in import_decl.name.value:
                        for type_decl in tree.type_declarations:
                            # Check class declaration within the java source code
                            if type(type_decl) is m.ClassDeclaration:
                                # Traverse through every field declared in the class
                                for fields in type_decl.body:
                                    try:
                                        self.recursive_classloader_function(fields, f, res)
                                    except Exception as e:
                                        common.logger.error("Unable to run class loader plugin " + str(e))
            except Exception as e:
                common.logger.debug("Plyj parser failed while parsing the file: " + filepath + "\nError" + str(e))
                continue

            try:
                for type_decl in tree.type_declarations:
                    # Check class declaration within the java source code
                    if type(type_decl) is m.ClassDeclaration:
                        # Traverse through every field declared in the class
                        for fields in type_decl.body:
                            try:
                                self.recursive_register_receiver_function(fields, f, res)
                            except Exception as e:
                                common.logger.error("Unable to run register receiver function plugin " + str(e))
            except Exception as e:
                common.logger.debug("Plyj parser failed while parsing the file: " + filepath + "\nError" + str(e))
                continue

        # Arrange the Broadcast Receivers created Dynamically in column format and store it in the variable -> Broadcast_Receiver
        br_list = "\n".join(receivers_list)

        if receivers_list:
            # Report the issue in the file and display it on the terminal
            PluginUtil.reportWarning(filepath, broadcast_receiver(br_list), res)

        queue.put(res)
예제 #2
0
def testReportIssue():
    res = []
    PluginUtil.reportIssue('fileName', 'details', res)
    assert len(res) == 2
    assert res[0].getCategory() == ExploitType.PLUGIN
    assert res[0].getSeverity() == Severity.VULNERABILITY
    assert res[0].getFile() == 'fileName'
    assert res[0].getDetails() == 'details'
    assert res[1].getLevel() == Severity.VULNERABILITY
    assert res[1].getData() == 'details'
예제 #3
0
 def recursive_insecure_call_function(self, fields, file, res):
     if type(fields) is m.MethodDeclaration:
         if str(fields.name) == self.CALL_FUNCTION:
             PluginUtil.reportInfo(filepath, insecure_function(filepath), res)
     elif type(fields) is list:
         for fieldname in fields:
             self.recursive_insecure_call_function(fieldname, file, res)
     elif hasattr(fields, '_fields'):
         for fieldname in fields._fields:
             self.recursive_insecure_call_function(getattr(fields, fieldname), file, res)
     return
예제 #4
0
    def target(self, queue):
        f = str(common.manifest)
        res = []
        count = 0
        ordered_broadcast = []
        path_variable_list =[]
        launch_mode_list =[]
        global fileName
        # full path to app manifest
        fileName = qarkMain.find_manifest_in_source()

        receivers = self.UserCreatedReceivers()
        for receiver in receivers:
            if "exported" and "true" in str(receiver):
                if not any(re.findall(self.PRIORITY_REGEX, str(receiver))):
                    ordered_broadcast.append(str(receiver))

        # Arrange exported broadcast receiver without priority set in column format
        list_orderedBR = " \n".join(ordered_broadcast)
        if ordered_broadcast:
            PluginUtil.reportWarning(fileName, self.OrderedBroadcastIssueDetails(list_orderedBR), res)

        for line in f.splitlines():
            count += 1
            # update progress bar
            pub.sendMessage('progress', bar=self.name, percent=round(count * 100 / len(f.splitlines())))

            if any(re.findall(self.PATH_USAGE, line)):
                path_variable_list.append(line)

            if any(re.findall(self.LAUNCH_MODE, line)):
                launch_mode_list.append(line)

            if any(re.findall(self.TASK_REPARENTING, line)):
                PluginUtil.reportInfo(fileName, self.TaskReparentingIssue(fileName), res)

        # Arrange identified path variable and launch mode usage in column format
        path_variable = " \n".join(path_variable_list)
        launch_mode_variable = "\n".join(launch_mode_list)

        if path_variable_list:
            PluginUtil.reportWarning(fileName, self.PathUsageIssue(path_variable), res)

        if launch_mode_list:
            PluginUtil.reportInfo(fileName, self.LaunchModeIssue(launch_mode_variable), res)

        # Check for google safebrowsing API
        if "WebView" in f.splitlines():
            if "EnableSafeBrowsing" and "true" not in f.splitlines():
                PluginUtil.reportInfo(fileName, self.SafebrowsingIssueDetails(fileName), res)

        # send all results back to main thread
        queue.put(res)
예제 #5
0
 def recursive_classloader_function(self, fields, f, res):
     if type(fields) is m.MethodDeclaration:
         if str(fields.name) == self.CLASS_LOADER:
             PluginUtil.reportInfo(filepath, class_loader(filepath), res)
         elif self.CLASS_LOADER in str(fields):
             PluginUtil.reportInfo(filepath, class_loader(filepath), res)
     elif type(fields) is list:
         for tree_object_fields in fields:
             self.recursive_classloader_function(tree_object_fields, f, res)
     elif hasattr(fields, '_fields'):
         for values in fields._fields:
             self.recursive_classloader_function(getattr(fields, values), f, res)
     return
예제 #6
0
    def target(self, queue):
        # get all decompiled files that contains usage of TelephonyManager
        files = common.text_scan(common.java_files, self.telephonyManagerRegex)

        res = []
        count = 0
        for f in files:
            count += 1
            pub.sendMessage('progress', bar=self.getName(), percent=round(count * 100 / len(files)))

            # get decompiled file body
            fileName = f[1]
            with open(fileName, 'r') as fi:
                fileBody = fi.read()

            # report if file contains inline call
            if PluginUtil.contains(self.inlineRegex, fileBody):
                PluginUtil.reportInfo(fileName, self.PhoneIdentifierIssueDetails(fileName), res)
                break

            # report if any TelephonyManager variables invokes calls to get phone identifiers
            for varName in PluginUtil.returnGroupMatches(self.varNameRegex, 2, fileBody):
                if PluginUtil.contains(r'%s\.(getLine1Number|getDeviceId)\(.*?\)' % varName, fileBody):
                    PluginUtil.reportInfo(fileName, self.PhoneIdentifierIssueDetails(fileName), res)
                    break

        queue.put(res)
예제 #7
0
    def target(self, queue):
        # get all decompiled files that contains usage of WebView
        files = common.text_scan(common.java_files, self.webViewRegex)

        res = []
        count = 0
        for f in files:
            count += 1
            pub.sendMessage('progress', bar=self.getName(), percent=round(count * 100 / len(files)))

            # get decompiled file body
            fileName = f[1]
            with open(fileName, 'r') as fi:
                fileBody = fi.read()

            # report if file contains any inline calls
            if PluginUtil.contains(self.inlineRegex, fileBody):
                PluginUtil.reportIssue(fileName, self.createIssueDetails(fileName), res)
                break

            # report if any WebView variables invoke calls
            for varName in PluginUtil.returnGroupMatches(self.varNameRegex, 2, fileBody):
                if PluginUtil.contains(r'%s\.addJavascriptInterface\(.*?\)' % varName, fileBody):
                    PluginUtil.reportIssue(fileName, self.createIssueDetails(fileName), res)
                    break

        queue.put(res)
예제 #8
0
    def target(self, queue):
        files = common.java_files
        global filepath, tree
        parser = plyj.Parser()
        tree = ''
        res = []
        count = 0
        for f in files:
            count += 1
            pub.sendMessage('progress', bar=self.name, percent=round(count * 100 / len(files)))
            filepath = str(f)
            try:
                tree = parser.parse_file(f)
            except Exception as e:
                common.logger.exception(
                    "Unable to parse the file and generate as AST. Error: " + str(e))
                continue

            try:
                for import_decl in tree.import_declarations:
                    # Check if Intent is called in the import statement
                    if 'Intent' in import_decl.name.value:
                        with open(filepath, 'r') as r:
                            file_body = r.read()
                        if PluginUtil.contains(self.NEW_TASK, file_body):
                            PluginUtil.reportInfo(filepath, new_task(filepath), res)
                            break
                        if PluginUtil.contains(self.MULTIPLE_TASK_TASK, file_body):
                            PluginUtil.reportInfo(filepath, multiple_task(filepath), res)
                            break
            except Exception as e:
                common.logger.debug("Plyj parser failed while parsing the file: " + filepath + "\nError" + str(e))
                continue

        queue.put(res)
예제 #9
0
    def target(self, queue):
        files = common.java_files
        global parser
        parser = plyj.Parser()
        global tree
        global fileName
        tree = ''
        res = []
        count = 0
        for f in files:
            count += 1
            pub.sendMessage('progress', bar=self.name, percent=round(count * 100 / len(files)))
            fileName = str(f)
            try:
                tree = parser.parse_file(f)
            except Exception:
                continue

            try:
                global url
                url = []
                for import_decl in tree.import_declarations:
                    if 'HttpURLConnection' in import_decl.name.value or 'URL' in import_decl.name.value:
                        textfile = str(open(fileName, 'r').read())
                        search = "http://"
                        http_result = re.findall('\\b'+search+'\\b', textfile)
                        if http_result:
                            url = re.findall(self.http_url_regex, textfile)
                            http_url_list = " \n".join(url)
                            PluginUtil.reportInfo(fileName, self.HardcodedHTTPUrlsIssueDetails((fileName, http_url_list)), res)
                            break
                        else:
                            continue
            except Exception:
                continue
        queue.put(res)
예제 #10
0
def test_check_perm_regex7():
    assert PluginUtil.contains(plugin.CHECK_PERMISSION, 'SelfUriPermission') is False
예제 #11
0
def test_check_perm_regex2():
    assert PluginUtil.contains(plugin.CHECK_PERMISSION, 'checkPermission') is True
예제 #12
0
def test_regex12():
    text = 'priority'
    assert PluginUtil.contains(plugin.PRIORITY_REGEX, text) is True
예제 #13
0
def testGetVarNameWithoutPackageName():
    text = 'TelephonyManager paramContext;'
    res = PluginUtil.returnGroupMatches(plugin.varNameRegex, 2, text)
    assert len(res) == 1
    assert res[0] == 'paramContext'
예제 #14
0
def test_regex5():
    assert not PluginUtil.contains(plugin.CHECK_PUBLIC_DIR, 'GetExternalStoragePublicDirectory')
예제 #15
0
def test_regex2():
    text = 'intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);'
    assert not PluginUtil.contains(plugin.NEW_TASK, text)
def test_regex2():
    assert PluginUtil.contains(plugin.CLASS_LOADER, 'loadClass') is True
예제 #17
0
def test_regex():
    text = 'intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);'
    assert PluginUtil.contains(plugin.NEW_TASK, text)
예제 #18
0
def test_regex5():
    text = 'intent.setFlags(Intent.FLAGACTIVITYMULTIPLETASK);'
    assert not PluginUtil.contains(plugin.MULTIPLE_TASK, text)
예제 #19
0
def testTwoGroupMatches():
    res = PluginUtil.returnGroupMatches(r'(test123)', 1, 'test123test321test123')
    assert len(res) == 2
    assert res[0] == 'test123'
    assert res[1] == 'test123'
예제 #20
0
def testOneGroupMatch():
    res = PluginUtil.returnGroupMatches(r'(test123)', 1, 'test321test123test321')
    assert len(res) == 1
    assert res[0] == 'test123'
예제 #21
0
def testZeroGroupMatches():
    assert len(PluginUtil.returnGroupMatches(r'(test123)', 1, 'test321')) == 0
예제 #22
0
def test_enforce_perm_regex2():
    text = 'enforcePermission'
    assert PluginUtil.contains(plugin.ENFORCE_PERMISSION, text) is True
def test_regex3():
    assert PluginUtil.contains(plugin.CLASS_LOADER, 'Classload') is False
예제 #24
0
def test_enforce_perm_regex8():
    text = 'enforcePermission("santos.benign.permission","Not allowed to start MyService")'
    assert PluginUtil.contains(plugin.ENFORCE_PERMISSION, text) is True
def test_regex5():
    assert PluginUtil.contains(plugin.DYNAMIC_BROADCAST_RECEIVER, 'RegisterReceiver') is False
예제 #26
0
def test_regex1():
    text = 'intent.setFlags(Intent.FLAGACTIVITYNEWTASK);'
    assert not PluginUtil.contains(plugin.NEW_TASK, text)
def test_regex():
    assert PluginUtil.contains(plugin.DEX_CLASS_LOADER, 'DexClassLoader') is True
예제 #28
0
def testInlineWithoutPackageName():
    text = '((TelephonyManager)paramContext.getSystemService("phone")).getLine1Number();'
    assert PluginUtil.contains(plugin.inlineRegex, text) is True
def test_regex1():
    assert PluginUtil.contains(plugin.DEX_CLASS_LOADER, 'ClassLoader') is False
예제 #30
0
def testGetVarNameInstantiation():
    text = 'TelephonyManager paramContext = (TelephonyManager)paramContext.getSystemService("phone"));'
    res = PluginUtil.returnGroupMatches(plugin.varNameRegex, 2, text)
    assert len(res) == 1
    assert res[0] == 'paramContext'
예제 #31
0
    def target(self, queue):
        f = str(common.manifest)
        res = []
        count = 0
        ordered_broadcast = []
        path_variable_list = []
        launch_mode_list = []
        global fileName
        # full path to app manifest
        fileName = qarkMain.find_manifest_in_source()

        receivers = self.UserCreatedReceivers()
        for receiver in receivers:
            if "exported" and "true" in str(receiver):
                if not any(re.findall(self.PRIORITY_REGEX, str(receiver))):
                    ordered_broadcast.append(str(receiver))

        # Arrange exported broadcast receiver without priority set in column format
        list_orderedBR = " \n".join(ordered_broadcast)
        if ordered_broadcast:
            PluginUtil.reportWarning(
                fileName, self.OrderedBroadcastIssueDetails(list_orderedBR),
                res)

        for line in f.splitlines():
            count += 1
            # update progress bar
            pub.sendMessage('progress',
                            bar=self.name,
                            percent=round(count * 100 / len(f.splitlines())))

            if any(re.findall(self.PATH_USAGE, line)):
                path_variable_list.append(line)

            if any(re.findall(self.LAUNCH_MODE, line)):
                launch_mode_list.append(line)

            if any(re.findall(self.TASK_REPARENTING, line)):
                PluginUtil.reportInfo(fileName,
                                      self.TaskReparentingIssue(fileName), res)

        # Arrange identified path variable and launch mode usage in column format
        path_variable = " \n".join(path_variable_list)
        launch_mode_variable = "\n".join(launch_mode_list)

        if path_variable_list:
            PluginUtil.reportWarning(fileName,
                                     self.PathUsageIssue(path_variable), res)

        if launch_mode_list:
            PluginUtil.reportInfo(fileName,
                                  self.LaunchModeIssue(launch_mode_variable),
                                  res)

        # Check for google safebrowsing API
        if "WebView" in f.splitlines():
            if "EnableSafeBrowsing" and "true" not in f.splitlines():
                PluginUtil.reportInfo(fileName,
                                      self.SafebrowsingIssueDetails(fileName),
                                      res)

        # send all results back to main thread
        queue.put(res)
예제 #32
0
def testContains():
    assert PluginUtil.contains(r'test123', 'test123') is True
예제 #33
0
def test_regex2():
    text = '"NtY163ManCAb"'
    assert not PluginUtil.contains(plugin.API_KEY_REGEX, text)
예제 #34
0
def testlog_regex1():
    assert PluginUtil.contains(plugin.debug_regex, 'd') is False
예제 #35
0
def test_regex4():
    text = 'public static final String API_TOKEN = "1234thisisaninvalidapitoken937235"'
    assert PluginUtil.contains(plugin.API_KEY_REGEX, text)
예제 #36
0
def test_check_perm_regex6():
    assert PluginUtil.contains(plugin.CHECK_PERMISSION, 'checkCalling') is False
예제 #37
0
def test_regex5():
    text = 'public static final String API_TOKEN = "$%#%~!^"'
    assert PluginUtil.contains(plugin.SPECIAL_CHAR_REGEX, text)
예제 #38
0
def test_enforce_perm_regex1():
    text = 'enforceCallingOrSelfUriPermission'
    assert PluginUtil.contains(plugin.ENFORCE_PERMISSION, text) is True
예제 #39
0
def test_regex1():
    text = 'public static final String API_TOKEN = "Nti4kWY-qRHTYq3dsbeip0P1tbGCzs2BAY163ManCAb"'
    assert PluginUtil.contains(plugin.API_KEY_REGEX, text)
예제 #40
0
def test_enforce_perm_regex6():
    text = 'enforceCallingPermission'
    assert PluginUtil.contains(plugin.ENFORCE_PERMISSION, text) is False
예제 #41
0
def test_regex1():
    assert PluginUtil.contains(plugin.PATH_USAGE,
                               'android:pathPrefix=') is False
예제 #42
0
def test_check_perm_regex1():
    assert PluginUtil.contains(plugin.CHECK_PERMISSION, 'checkCallingOrSelfUriPermission') is True
예제 #43
0
def test_regex2():
    assert PluginUtil.contains(plugin.PATH_USAGE,
                               'android:pathPattern') is False
예제 #44
0
def test_regex5():
    text = 'intent.setFlags(Intent.FLAGACTIVITYMULTIPLETASK);'
    assert not PluginUtil.contains(plugin.MULTIPLE_TASK, text)
예제 #45
0
def test_regex3():
    text = "android:launchMode='singleTask'"
    assert PluginUtil.contains(plugin.LAUNCH_MODE, text) is True
예제 #46
0
def test_regex3():
    assert not PluginUtil.contains(plugin.CHECK_EXTERNAL_MEDIA, 'GetExternalMediaDirs')
예제 #47
0
    def target(self, queue):
        global filepath, tree
        files = common.java_files
        parser = plyj.Parser()
        tree = ''
        external_pub_dir, external_media, external_storage, res = (
            [] for _ in xrange(4))
        count = 0
        for f in files:
            count += 1
            pub.sendMessage('progress',
                            bar=self.name,
                            percent=round(count * 100 / len(files)))
            filepath = str(f)
            try:
                tree = parser.parse_file(f)
            except Exception as e:
                common.logger.exception(
                    "Unable to parse the file and generate as AST. Error: " +
                    str(e))
                continue
            try:
                for import_decl in tree.import_declarations:
                    if 'File' in import_decl.name.value:
                        with open(filepath, 'r') as fr:
                            file_body = fr.read()
                        if PluginUtil.contains(self.CHECK_EXTERNAL_STORAGE,
                                               file_body):
                            external_storage.append(filepath)
                            break

                        if PluginUtil.contains(self.CHECK_EXTERNAL_MEDIA,
                                               file_body):
                            external_media.append(filepath)
                            break

                        if PluginUtil.contains(self.CHECK_PUBLIC_DIR,
                                               file_body):
                            external_pub_dir.append(filepath)
                            break

            except Exception as e:
                common.logger.debug(
                    "Plyj parser failed while parsing the file: " + filepath +
                    "\nError" + str(e))
                continue

        # Store the content obtained above in a column format
        storage = "\n".join(external_storage)
        media = "\n".join(external_media)
        pub_dir = "\n".join(external_pub_dir)

        if external_storage:
            PluginUtil.reportWarning(filepath, check_external_storage(storage),
                                     res)

        if external_media:
            PluginUtil.reportWarning(filepath, check_media_directory(media),
                                     res)

        if external_pub_dir:
            PluginUtil.reportWarning(filepath, check_public_directory(pub_dir),
                                     res)

        queue.put(res)
예제 #48
0
def test_regex():
    assert PluginUtil.contains(plugin.CHECK_EXTERNAL_STORAGE, 'getExternalFilesDir')
예제 #49
0
def test_regex5():
    text = "android:allowTaskReparenting='true'"
    assert PluginUtil.contains(plugin.TASK_REPARENTING, text) is True
예제 #50
0
def testInlineGetDeviceId():
    text = '((android.telephony.TelephonyManager)paramContext.getSystemService("phone")).getDeviceId();'
    assert PluginUtil.contains(plugin.inlineRegex, text) is True
예제 #51
0
def test_regex6():
    text = 'android:allowTaskReparenting="true"'
    assert PluginUtil.contains(plugin.TASK_REPARENTING, text) is True
예제 #52
0
def testGetVarNameLastArgument():
    text = 'void func(int i, TelephonyManager paramContext)'
    res = PluginUtil.returnGroupMatches(plugin.varNameRegex, 2, text)
    assert len(res) == 1
    assert res[0] == 'paramContext'
예제 #53
0
def test_regex8():
    text = '<receiver android:name=".FormatOutgoingCallReceiver" android:enabled="true" android:exported="true"'
    assert PluginUtil.contains(plugin.RECEIVER_REGEX, text) is False
예제 #54
0
def testTelephonyManagerRegex():
    assert PluginUtil.contains(plugin.telephonyManagerRegex, 'import android.telephony.TelephonyManager') is True
예제 #55
0
def test_regex11():
    text = 'Priority'
    assert PluginUtil.contains(plugin.PRIORITY_REGEX, text) is False
예제 #56
0
def test_regex4():
    text = 'android:launchMode="singleTask"'
    assert PluginUtil.contains(plugin.LAUNCH_MODE, text) is True
예제 #57
0
def testNotContains():
    assert PluginUtil.contains(r'test123', 'test321') is False