Exemplo n.º 1
0
    def run(self):
        result = {
            "title": "Application Uses Deprecated Ciphers",
            "details": "",
            "severity": "Low",
            "report": False
        }

        # preparing variable to run
        ciphers = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            #ssl_socket_files = pretty_grep(self.file_regex, smali)
            ciphers.update(pretty_grep(self.regex, smali))

        if ciphers:
            result.update({
                "report":
                True,
                "details":
                pretty_grep_to_str(ciphers, self.decompiled_apk, ignore)
            })

        return {"{}_result".format(self.name()): result}
Exemplo n.º 2
0
    def run(self):
        result = {
            "title": "Application Does Not Implement Root Detection",
            "details": "",
            "severity": "High",
            "report": True
        }

        # preparing variable to run
        root_detection = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            root_detection.update(pretty_grep(self.regex, smali))

        if root_detection:
            result = {
                "title":
                "Application Has Root Detection",
                "details":
                pretty_grep_to_str(root_detection, self.decompiled_apk,
                                   ignore),
                "severity":
                "Low",
                "report":
                True
            }

        return {"{}_result".format(self.name()): result}
Exemplo n.º 3
0
    def run(self):
        result = {
            "title": "Application Does Not Check For Third-Party Keyboards",
            "details": "",
            "severity": "Low",
            "report": False
        }

        # preparing variable to run
        third_party_keyboard_evidence = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            third_party_keyboard_evidence.update(pretty_grep(
                self.regex, smali))

            # remove ignored paths
            to_remove = []
            for filename in third_party_keyboard_evidence:
                if any(filepath in filename for filepath in ignore):
                    to_remove += [filename]
            for filename in to_remove:
                third_party_keyboard_evidence.pop(filename)

        if not third_party_keyboard_evidence:
            result.update({"report": True})

        return {"{}_result".format(self.name()): result}
Exemplo n.º 4
0
    def run(self):
        result = {
            "title": "Application Does Not Implement SSL Pinning",
            "details": "",
            "severity": "High",
            "report": False
        }

        # preparing variable to run
        ssl_keywords = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali for SSL evidences")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            ssl_keywords.update(pretty_grep(self.regex, smali))

        if not ssl_keywords:
            result.update({
                "report": True,
                "details": "Found no evidences of a `TrustManager`."
            })

        Log.info("Analysing SSL evidences")

        for filename in ssl_keywords:
            if any(filepath in filename for filepath in ignore):
                continue

            with open(filename, "r") as fp:
                smali = fp.read()

            if re.search(self.mock_check_server, smali):
                result.update({
                    "report":
                    True,
                    "details":
                    "{}\n* {}:{}\n".format(
                        result["details"],
                        filename.replace(self.decompiled_apk, ""),
                        extract_smali_method("checkServerTrusted", filename))
                })

            if re.search(self.mock_accepted_issuers, smali):
                result.update({
                    "report":
                    True,
                    "details":
                    "{}\n* {}:{}\n".format(
                        result["details"],
                        filename.replace(self.decompiled_apk, ""),
                        extract_smali_method("getAcceptedIssuers", filename))
                })

        return {"{}_result".format(self.name()): result}
Exemplo n.º 5
0
    def run(self):
        result = {
            "title": "Application's WebViews Enable JavaScript",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        # preparing variable to run
        filenames = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            filenames.update(pretty_grep(self.regex, smali))

        report = {}
        # check var setting
        for file_name in filenames:
            report[file_name] = []

            for instance in filenames[file_name]:
                var_name = instance["details"].split(
                    "}", 1)[0].split(",", 1)[-1].strip()

                var_setting = track_variable(
                    var_name, instance["line"], file_name)

                for setting_line in var_setting:
                    if "0x1" in setting_line["details"]:
                        report[file_name] += var_setting

        for file_name in report:
            filenames[file_name] += report[file_name]

        if filenames:
            result.update({
                "report": True,
                "details": pretty_grep_to_str(
                    filenames, self.decompiled_apk, ignore)
            })

        return {
            "{}_result".format(self.name()): result
        }
Exemplo n.º 6
0
    def run(self):
        result = {
            "title": "Application Communicates Over Unencrypted Channels",
            "details": "",
            "severity": "High",
            "report": False
        }

        # preparing variable to run
        pretty_result = ""
        ignore = [url.strip() for url in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            urls = pretty_grep(self.regex, smali)
            to_remove = []
            for url in urls:
                for detail in urls[url]:
                    if any(iurl in detail["details"] for iurl in ignore) or \
                    detail["details"] == "http://":
                        urls[url].remove(detail)

                    if not urls[url]:
                        to_remove += [url]

            for filename in to_remove:
                urls.pop(filename)

            pretty_result += pretty_grep_to_str(urls, smali)

        if pretty_result:
            result.update({
                "report": True,
                "details": pretty_result
            })

        return {
            "{}_result".format(self.name()): result
        }
Exemplo n.º 7
0
    def run(self):
        result = {
            "title": "Application's WebViews Implement Javascript Bridges",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        # preparing variable to run
        bridges = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            bridges.update(pretty_grep(self.js_interface_regex, smali))

        report = {}
        # check var setting
        for file_name in bridges:
            report[file_name] = []

            for instance in bridges[file_name]:
                report[file_name] += method_name(instance["line"], file_name)

        bridges = {}  # TODO: check this works
        for file_name in report:
            bridges[file_name] += report[file_name]

        if bridges:
            result.update({
                "report":
                True,
                "details":
                pretty_grep_to_str(bridges, self.decompiled_apk, ignore)
            })

        return {"{}_result".format(self.name()): result}
Exemplo n.º 8
0
    def run(self):
        result = {
            "title": "Application Does Not Prevent Screenshots",
            "details": "",
            "severity": "Low",
            "report": False
        }

        # preparing variable to run
        report_activities = []
        activities = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            activities.update(pretty_grep(self.activities_regex, smali))

        if activities:
            safe_activities = pretty_grep(
                self.regex, " ".join(list(activities)))
            report_activities = list(set(activities) - set(safe_activities))

        if report_activities:
            result.update({
                "report": True,
                "details": "* {}".format("\n* ".join(
                    [activity.replace(self.decompiled_apk, "")
                    for activity in report_activities if not any(
                        i in activity for i in ignore)
                    ])
                )
            })

        return {
            "{}_result".format(self.name()): result
        }
Exemplo n.º 9
0
    def run(self):
        result = {
            "title": "Application's WebViews Are Vulnerable To Arbitrary \
Redirection",
            "details": "",
            "severity": "Low",
            "report": False
        }

        # preparing variable to run
        webview_files = {}
        overrride_url_files = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            webview_files.update(pretty_grep(self.use_webview_regex, smali))
            overrride_url_files.update(pretty_grep(self.regex, smali))

        Log.info("Analysing WebViews")

        for filename in overrride_url_files:
            webview_files.pop(filename)

        if webview_files:
            result.update({
                "report":
                True,
                "details":
                pretty_grep_to_str(webview_files, self.decompiled_apk, ignore)
            })

        return {"{}_result".format(self.name()): result}
Exemplo n.º 10
0
    def run(self):
        result = {
            "title": "Application Is Vulnerable To Fragment Injection",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        # create yaml
        apktool_module = YamlModule()
        apktool_module.decompiled_apk = self.decompiled_apk
        apktool = apktool_module.run()
        if "print" in apktool:
            return {"print": "Could not get the apktool yaml file"}
        apktool = apktool.popitem()[1]

        # preparing variable to run
        activities = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's apktool yaml and smali")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            activities.update(pretty_grep(self.regex, smali))

        if activities and int(apktool.min_sdk()) < 18:
            result.update({
                "report":
                True,
                "details":
                pretty_grep_to_str(activities, self.decompiled_apk, ignore)
            })

        return {"{}_result".format(self.name()): result}
Exemplo n.º 11
0
    def run(self):
        result = {
            "title": "Application Does Not Delete Cached Files On Exit",
            "details": "",
            "severity": "Low",
            "report": False
        }

        # preparing variable to run
        webview_files = {}
        clear_cache = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali code")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            webview_files.update(pretty_grep(self.use_webview_regex, smali))
            clear_cache.update(pretty_grep(self.regex, smali))

        Log.info("Analysing WebViews")

        for filename in clear_cache:
            webview_files.pop(filename)

        if webview_files:
            result.update({
                "report":
                True,
                "details":
                pretty_grep_to_str(webview_files, self.decompiled_apk, ignore)
            })

        return {"{}_result".format(self.name()): result}
Exemplo n.º 12
0
    def run(self):
        result = {
            "title": "Application Does Not Detect Emulators",
            "details": "",
            "severity": "Medium",
            "report": True
        }

        # preparing variable to run
        emulator_detection = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing smali code for emulator detection mechanisms")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            emulator_detection.update(pretty_grep(self.regex, smali))

        if emulator_detection:
            result = {
                "title":
                "Application Detects Emulators",
                "details":
                "{}\n\n{}".format(
                    result["details"],
                    pretty_grep_to_str(emulator_detection, self.decompiled_apk,
                                       ignore)),
                "severity":
                "Medium",
                "report":
                True
            }

        # dynamic testing
        Log.info("Checking requirements for dynamic testing")

        if hasattr(self, "apk") and hasattr(self, "avd") and \
        hasattr(self, "identifier") and self.identifier and \
        self.apk and self.avd:
            # get available devices before starting the emulator
            available_devices = devices()

            # start emulator
            Log.info("Starting the emulator")
            emulator_process = process("emulator -avd {}".format(self.avd))

            # wait for emulator to start
            sleep(60)

            # diff devices -> get emulator
            emulator_id = list(set(devices()) - set(available_devices))

            if len(emulator_id) != 1:
                Log.warn("Could not find the emulator in the device list")
                emulator_process.kill()
                return {
                    "{}_result".format(self.name()): result,
                    "print": "Coud not start emulator or find defined avd"
                }

            device = AndroidDevice(emulator_id)

            Log.info("Installing the apk in the device")
            device.install(self.apk)
            if device.installed(self.identifier):

                while not device.unlocked():
                    Log.info("Please unlock the emulator")
                    sleep(5)

                Log.info("Starting the application")
                device.start(identifier)
                sleep(15)

                if self.identifier not in device.processes():
                    result.update({"report": False})

            emulator_process.kill()

        return {"{}_result".format(self.name()): result}
Exemplo n.º 13
0
    def run(self):
        from time import sleep
        result = {
            "title": "Application Does Not Implement SSL Pinning",
            "details": "",
            "severity": "High",
            "report": False
        }

        # preparing variable to run
        ssl_keywords = {}
        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Analysing application's smali for SSL evidences")
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            ssl_keywords.update(pretty_grep(self.regex, smali))

        if not ssl_keywords:
            result.update({
                "report": True,
                "details": "Found no evidences of a `TrustManager`."
            })

        Log.info("Analysing SSL evidences")

        for filename in ssl_keywords:
            if any(filepath in filename for filepath in ignore):
                continue

            with open(filename, "r") as fp:
                smali = fp.read()

            if re.search(self.mock_check_server, smali):
                result.update({
                    "report":
                    True,
                    "details":
                    "{}\n* {}:{}\n".format(
                        result["details"],
                        filename.replace(self.decompiled_apk, ""),
                        extract_smali_method("checkServerTrusted", filename))
                })

            if re.search(self.mock_accepted_issuers, smali):
                result.update({
                    "report":
                    True,
                    "details":
                    "{}\n* {}:{}\n".format(
                        result["details"],
                        filename.replace(self.decompiled_apk, ""),
                        extract_smali_method("getAcceptedIssuers", filename))
                })

        if self.device and self.identifier and \
        self.proxy_host != None and self.proxy_port != None:
            Log.info("Testing SSL Pinning using a proxy")
            Log.info(
                "Make sure your device trusts the CA in: {}/ca.crt".format(
                    _CERT_PATH))
            Log.info("Waiting for {} seconds to allow time to setup the \
proxy on the remote device".format(self.wait_time))
            sleep(int(self.wait_time))

            Log.info("Killing the application")
            self.device.stop(self.identifier)

            Log.info("Starting the SSL proxy")
            proxy_server = create_server(self.proxy_host, self.proxy_port,
                                         _CERT_PATH)

            Log.info("Starting the Application")
            self.device.start(self.identifier)

            Log.info("Waiting for the Application to start and make requests")
            sleep(10)

            pinned = list(
                set(proxy_server.server.connected) -
                set(proxy_server.server.requested))

            if not proxy_server.server.connected:
                Log.error("No connections made by the application")

            if pinned:
                result.update({
                    "title":
                    "Application Implements SSL Pinning",
                    "report":
                    True,
                    "details":
                    "{}\n\nThe application started a connection but \
made no requests to the following domains:\n* {}".format(
                        result["details"], "\n* ".join(pinned))
                })

            proxy_server.stop()

        return {"{}_result".format(self.name()): result}
Exemplo n.º 14
0
    def run(self):
        result = {
            "title": "Application Does Not Detect Debuggers",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        ignore = [filepath.strip() for filepath in self.ignore.split(";")]

        Log.info("Identifying smali directories")
        dirs = smali_dirs(self.decompiled_apk)

        Log.info("Looking for evidence in smali code")
        debug_evidence = {}
        for directory in dirs:
            smali = "{}/{}".format(self.decompiled_apk, directory)
            debug_evidence.update(pretty_grep(self.debug_regex, smali))

        if debug_evidence:
            result.update({
                "title":
                "Application Destects Debuggers",
                "report":
                True,
                "details":
                "The following evidence was found in the smali \
code:\n{}".format(
                    pretty_grep_to_str(debug_evidence, self.decompiled_apk,
                                       ignore))
            })
        else:
            result.update({
                "details": "No evidence of debug detection was found in the \
smali code.",
                "report": True
            })

        if self.repackage:
            Log.info("Trying to modify the application to be debuggable")

            # make the application debuggable
            debug_module = DModule()
            debug_module.decompiled_apk = self.decompiled_apk
            debug_module.device = self.device
            debug_module.output = None  # will default to /tmp
            debug_module.install = True
            debug_module.run()

        Log.info("Starting the application and identifying the process ID")
        self.device.start(self.identifier)
        pid = self.device.pid(self.identifier)

        if pid:
            Log.info("Forwarding local ports")
            forward(54321, pid)

            Log.info("Starting JDB")
            jdb = JDB("127.0.0.1", 54321)

            if not jdb.running():
                result.update({
                    "report":
                    True,
                    "details":
                    "{}\n\nScrounger was unable to attach a debugger\
 to the application.".format(result["details"])
                })
            else:
                result.update({
                    "report":
                    True,
                    "details":
                    "{}\n\nScrounger was able to attach a debugger \
to the application:\n\n{}".format(result["details"], jdb.read())
                })

            Log.info("Removing forwarded ports and exiting jdb")
            remove_forward()
            jdb.exit()

        else:
            Log.error("The application is not running")

        return {"{}_result".format(self.name()): result}