Пример #1
0
    def run(self):
        result = {
            "title": "Application Does Not Use Prepared Statements",
            "details": "",
            "severity": "Low",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        sqlite_matches = re.findall(self._sqlite_regex, symbols)
        matches = re.findall(self._regex, symbols)
        if sqlite_matches and not matches:
            result.update({
                "report":
                True,
                "details":
                "Evidences of SQLite being used were found but no \
evidence of prepared statements being used was found."
            })

        return {"{}_result".format(self.name()): result}
Пример #2
0
    def run(self):
        result = {
            "title": "Application Does Not Check For Third-Party Keyboards",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        if not re.search(self._regex, symbols):
            result.update({
                "report":
                True,
                "details":
                "No evidence of third party keyboard detection \
functions found."
            })

        return {"{}_result".format(self.name()): result}
Пример #3
0
    def run(self):
        result = {
            "title": "Application Logs To Syslog",
            "details": "",
            "severity": "Low",
            "report": True
        }

        Log.info("Getting executable's name")

        info_module = InfoModule()
        info_module.identifier = self.identifier
        info_module.device = self.device
        info_result, info = info_module.run(), None
        for key in info_result:
            if key.endswith("_info"):
                info = info_result[key]

        if not info:
            return {"print": "Couldn't get Info from device."}

        executable_name = info["CFBundleExecutable"]

        Log.info("Getting application's logs")
        logs = self.device.logs(executable_name)

        if logs:
            result.update({
                "report":
                True,
                "details":
                "The following logs were found:\n{}".format(logs)
            })

        return {"{}_result".format(self.name()): result}
Пример #4
0
    def run(self):
        result = {
            "title": "Application Does Not Target The Latest SDK",
            "details": "",
            "severity": "Low",
            "report": False
        }

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

        self.apktool = self.apktool.popitem()[1]

        Log.info("Analysing application's apktool yaml")

        target_sdk = self.apktool.target_sdk()
        if target_sdk and int(target_sdk) < int(self.targetsdk):
            result.update({
                "report":
                True,
                "details":
                "* Current target supported SDK \
version\ntargetSdkVersion=\"{}\"".format(target_sdk)
            })

        return {
            "{}_result".format(self.name()): result,
            "{}_targetsdk".format(self.apktool.apk_filename()): target_sdk
        }
Пример #5
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}
Пример #6
0
    def run(self):
        Log.info("Creating decompilation directory")

        # create decompiled directory
        identifier = self.apk.rsplit("/", 1)[-1].lower().rsplit(".", 1)[0]
        output_path = "{}/{}.decompiled".format(self.output, identifier)
        execute("mkdir -p {}".format(output_path))

        # unzip
        Log.info("Decompiling application")
        decompile(self.apk, output_path)

        # get identifier
        manifest_module = ManifestModule()
        manifest_module.decompiled_apk = output_path
        self.manifest = manifest_module.run()
        if "print" not in self.manifest:
            identifier = self.manifest.popitem()[1].package()

            # move decompiled app to new path
            old_output_path = output_path
            output_path = "{}/{}.decompiled".format(self.output, identifier)
            execute("mv {} {}".format(old_output_path, output_path))

        return {
            "{}_decompiled".format(identifier): output_path,
            "print": "Application decompiled to {}".format(output_path)
        }
Пример #7
0
    def run(self):
        result = {
            "title": "Application Allows Files To Be Backed Up",
            "details": "",
            "severity": "Low",
            "report": False
        }

        Log.info("Checking if the application is installed")
        installed_apps = self.device.apps()

        if self.identifier not in installed_apps:
            return {"print": "Application not installed."}

        remote_data_path = installed_apps[self.identifier]["data"]

        files = self.device.find_files(remote_data_path)

        report_files = []
        for file_path in files:
            if file_path:
                protection = self.device.backup_flag(file_path)
                if protection and "0" in protection:
                    report_files += [file_path]

        if report_files:
            result.update({
                "report":
                True,
                "details":
                "The following files were found to have the \
backup flag:\n* {}".format("\n* ".join(report_files))
            })

        return {"{}_result".format(self.name()): result}
    def run(self):
        result = {
            "title": "Application Communicates Over Unencrypted Channels",
            "details": "",
            "severity": "Medium",
            "report": False
        }
        ignore = [url.strip() for url in self.ignore.split(";")]

        Log.info("Getting application's strings")
        strs = strings(self.binary)

        Log.info("Analysing strings")
        report_matches = []
        matches = re.finditer(self._regex, strs)
        for item in matches:
            match = item.group()
            if any(iurl in match for iurl in ignore) or match == "http://":
                continue
            report_matches += [match]

        if report_matches:
            result.update({
                "report":
                True,
                "details":
                "The following strings were found:\n* {}".format("\n* ".join(
                    sorted(set(report_matches))))
            })

        return {"{}_result".format(self.name()): result}
Пример #9
0
    def run(self):
        result = {
            "title": "Application Has World Writable Files",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        if not self.device.installed(self.identifier):
            return {"print": "Application not installed"}

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

        sleep(5)

        Log.info("Analysing application's data")

        target_paths = self.device.data_paths(self.identifier)

        world_writable_files = []
        for data_path in target_paths:
            world_writable_files += self.device.world_files(data_path, "w")

        if world_writable_files:
            result.update({
                "report":
                True,
                "details":
                "* World Writable Files:\n * {}".format(
                    "\n* ".join(world_writable_files))
            })

        return {"{}_result".format(self.name()): result}
Пример #10
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}
Пример #11
0
    def run(self):
        result = {
            "title": "Application Uses Native Libraries",
            "details": "",
            "severity": "Low",
            "report": False
        }

        Log.info("Identifying application's libraries")
        libs_path = [lib.strip() for lib in self.libs.split(";")]

        libraries = []
        if self.device.installed(self.identifier):
            app_path = self.device.packages()[self.identifier].rsplit("/",
                                                                      1)[0]

            libs_path_str = " ".join(
                ["{}/{}".format(app_path, lib) for lib in libs_path])

            libraries = [
                lib for lib in self.device.root_execute("ls {}".format(
                    libs_path_str)).split("\n")
                if lib and "No such file or directory" not in lib
            ]

        if libraries:
            result.update({
                "report": True,
                "details": "* {}".format("\n* ".join(libraries))
            })

        return {"{}_result".format(self.name()): result}
Пример #12
0
    def run(self):
        result = {
            "title": "Application Was Compiled Without ARC Support",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        if not re.search(self._regex, symbols):
            result.update({
                "report": True,
                "details": "No evidence of ARC functions found."
            })

        return {"{}_result".format(self.name()): result}
Пример #13
0
    def run(self):
        # create unzipped directory
        identifier = self.ipa.rsplit("/", 1)[-1].lower().rsplit(".", 1)[0]

        Log.info("Crating output directories")
        output_path = "{}/{}.unzipped".format(self.output, identifier)
        execute("mkdir -p {}".format(output_path))

        # unzip
        Log.info("Unzipping application")
        unzip(self.ipa, output_path)

        # get new identifier
        app_path = application_path(output_path)

        # get info
        info_module = InfoModule()
        info_module.unzipped_ipa = output_path
        info = info_module.run()
        for key in info:
            if key.endswith("_info"):
                info = info[key]
                break

        # move to new directory
        if "CFBundleIdentifier" in info:
            identifier = info["CFBundleIdentifier"]
            old_output_path = output_path
            output_path = "{}/{}.unzipped".format(self.output, identifier)
            execute("mv {} {}".format(old_output_path, output_path))

        return {
            "{}_unzipped".format(identifier): output_path,
            "print": "Application unzipped to {}".format(output_path)
        }
Пример #14
0
    def run(self):
        result = {
            "title": "Application Makes Insecure Function Calls",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        matches = re.findall(self.function_calls, symbols)
        if matches:
            result.update({
                "report":
                True,
                "details":
                "The following function symbols were \
found: * {}".format("\n* ".join(sorted(set(matches))))
            })

        return {"{}_result".format(self.name()): result}
Пример #15
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}
Пример #16
0
    def run(self):
        result = {
            "title": "Application Does Not Implement SSL Pinning",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        Log.info("Getting application's strings")
        strs = strings(self.binary)

        Log.info("Analysing strings and class dump")
        matches = re.findall(self._regex, strs)
        evidence = pretty_grep(self._regex, self.class_dump)

        if matches:
            result.update({
                "report":
                True,
                "details":
                "The following strings were found:\n* {}".format("\n* ".join(
                    sorted(set(matches))))
            })

        if evidence:
            result.update({
                "report":
                True,
                "details":
                "{}\nThe following was found in the class dump:\n\
{}".format(result["details"], pretty_grep_to_str(evidence, self.class_dump))
            })

        return {"{}_result".format(self.name()): result}
Пример #17
0
    def run(self):
        result = {
            "title": "Application Does Not Disable Clipboard Access",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        if not re.search(self._regex, symbols):
            result.update({
                "report":
                True,
                "details":
                "No evidence of the application trying to disable \
clipboard access."
            })

        return {"{}_result".format(self.name()): result}
Пример #18
0
    def run(self):
        result = {
            "title": "Application Has Browsable Activities",
            "details": "",
            "severity": "Informational",
            "report": False
        }

        # create manifest
        manifest_module = ManifestModule()
        manifest_module.decompiled_apk = self.decompiled_apk
        self.manifest = manifest_module.run()
        if "print" in self.manifest:
            return {"print": "Could not get the manifest"}

        self.manifest = self.manifest.popitem()[1]

        Log.info("Getting browsable activities and uris")

        browsable_classes = self.manifest.browsable_activities()
        browsable_uris = self.manifest.browsable_uris()

        if browsable_classes or browsable_uris:
            details = "* URIs:\n * {}".format("\n * ".join(browsable_uris))
            details += "\n\n* Classes:\n * {}".format(
                "\n * ".join(browsable_classes))

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

        return {
            "{}_result".format(self.name()): result,
            "{}_browsable_classes".format(self.manifest.package()):
            browsable_classes,
            "{}_browsable_uris".format(self.manifest.package()): browsable_uris
        }
Пример #19
0
    def run(self):
        result = {
            "title": "Application Has Insecure ATS Configurations",
            "details": "",
            "severity": "Medium",
            "report": False
        }

        info_content = plist(self.info)

        Log.info("Parsing Info.plist file contents")
        ats_xml = plist_dict_to_xml(info_content, self._ats_key)

        Log.info("Analysing Info.plist file")
        if self._ats_key not in info_content or not info_content[
                self._ats_key]:
            result.update({
                "report":
                True,
                "details":
                "No evidence of ATS being implemented found."
            })

        if any(option in ats_xml for option in self._insecure_options):
            result.update({
                "report":
                True,
                "details":
                "The following insecure ATS configuration was \
found : {}".format(ats_xml)
            })

        return {"{}_result".format(self.name()): result}
Пример #20
0
    def run(self):

        # get the jar first
        jar_module = JarModule()
        jar_module.output = self.output
        jar_module.apk = self.apk
        result = jar_module.run()

        self.jar = [result[jar] for jar in result if jar.endswith("_jar")][0]
        if not self.jar:
            return {"print": "Could not decompile the application"}

        Log.info("Creating source directory")
        # create source directory
        identifier = self.jar.rsplit("/", 1)[-1].lower().rsplit(".", 1)[0]

        output_path = "{}/{}.source".format(self.output, identifier)
        execute("mkdir -p {}".format(output_path))

        # unzip
        Log.info("Getting application's source")
        source(self.jar, output_path)

        return {
            "{}_source".format(identifier): output_path,
            "print": "Application source reversed to {}".format(output_path)
        }
Пример #21
0
    def run(self):
        Log.info("Preparing to re-compile the application")

        # get identifier
        manifest_module = ManifestModule()
        manifest_module.decompiled_apk = self.decompiled_apk
        self.manifest = manifest_module.run()
        if "print" not in self.manifest:
            identifier = self.manifest.popitem()[1].package()

        recompiled_apk = "{}/{}-recompiled.apk".format(self.output, identifier)

        # unzip
        Log.info("Re-compiling application")
        output = recompile(self.decompiled_apk, recompiled_apk)

        if "Exception" in output:
            return {
                "print":
                "Failed to re-compile the application:\n{}".format(output)
            }

        return {
            "{}_recompiled".format(identifier): recompiled_apk,
            "print": "Application re-compiled to {}".format(recompiled_apk)
        }
Пример #22
0
    def run(self):
        result = {
            "title": "Application Not Compiled With PIE Support",
            "details": "",
            "severity": "Low",
            "report": False
        }

        flags_module = FlagsModule()
        flags_module.binary = self.binary
        flags_result, flags = flags_module.run(), None
        for key in flags_result:
            if key.endswith("_flags"):
                flags = flags_result[key]

        if not flags:
            return {"print": "Couldn't get flags from binary."}

        Log.info("Analysing Flags")
        matches = re.findall(self._regex, flags)
        if not matches:
            result.update({
                "report": True,
                "details": "PIE flag not found."
            })

        return {
            "{}_result".format(self.name()): result
        }
Пример #23
0
    def run(self):
        result = {
            "title": "Application Has Secret Codes",
            "details": "",
            "severity": "Low",
            "report": False
        }

        # create manifest
        manifest_module = ManifestModule()
        manifest_module.decompiled_apk = self.decompiled_apk
        self.manifest = manifest_module.run()
        if "print" in self.manifest:
            return {"print": "Could not get the manifest"}

        self.manifest = self.manifest.popitem()[1]

        Log.info("Analysing application's manifest for secret codes")
        secret_codes = self.manifest.secret_codes()

        if secret_codes:
            details = "* Secret Codes:\n * {}".format(
                "\n * ".join(secret_codes))
            details += """

* Test the secret codes using the following command:
adb shell su -c "am broadcast -a {} -d android_secret_code://CODE"
            """.format(self._secret_code_activity)
            result.update({"report": True, "details": details})

        return {
            "{}_result".format(self.name()): result,
            "{}_secret_codes".format(self.manifest.package()): secret_codes
        }
Пример #24
0
    def run(self):
        result = {
            "title": "Application Does Not Check If A Passcode Is Set",
            "details": "",
            "severity": "Low",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        matches = re.findall(self._regex, symbols)
        if not matches:
            result.update({
                "report":
                True,
                "details":
                "No evidence of checking for passcode set found."
            })

        return {"{}_result".format(self.name()): result}
Пример #25
0
    def run(self):
        Log.info("Preparing to sign the application")

        binaries_local_path = "{}/bin/android".format(_SCROUNGER_HOME)
        signjar = "{}/signapk.jar".format(binaries_local_path)
        key = "{}/key.pk8".format(binaries_local_path)
        cert = "{}/cert.x509.pem".format(binaries_local_path)

        # get identifier
        identifier = self.recompiled_apk.rsplit("/",1)[-1].rsplit(".", 1)[0]
        signed_apk = "{}/{}-signed.apk".format(self.output, identifier)

        # sign
        Log.info("Signinging application")
        output = sign(self.recompiled_apk, signed_apk, signjar, cert, key)

        if output and "Exception" in output:
            return {
                "print": "Failed to sign the application:\n{}".format(output)
            }

        return {
            "{}_signed".format(identifier): signed_apk,
            "print": "Application signed to {}".format(signed_apk)
        }
Пример #26
0
    def run(self):
        result = {
            "title": "Application Uses Weak Random Functions",
            "details": "",
            "severity": "Low",
            "report": False
        }

        symb_module = SymbolsModule()
        symb_module.binary = self.binary
        symbols_result, symbols = symb_module.run(), None
        for key in symbols_result:
            if key.endswith("_symbols"):
                symbols = symbols_result[key]

        if not symbols:
            return {"print": "Couldn't get symbols from binary."}

        Log.info("Analysing Symbols")
        matches = re.findall(self._regex, symbols)
        if matches:
            result.update({
                "report":
                True,
                "details":
                "The following evidence were found:\n* {}".format("\n* ".join(
                    sorted(set(matches))))
            })

        return {"{}_result".format(self.name()): result}
    def run(self):
        result = {
            "title":
            "Application's Providers Are Vulnerable To Path Traversal",
            "details": "",
            "severity": "High",
            "report": False
        }

        Log.info("Extracting and translating providers")
        providers = parsed_providers(self.decompiled_apk)

        Log.info("Analysing providers")

        vulnerable_providers = []
        example_result = None
        for provider in providers:
            exec_result = self.device.read_provider(provider,
                                                    self.exploit_path)

            if exec_result and "Exception" not in exec_result:
                vulnerable_providers += [provider]
                example_result = exec_result

        if vulnerable_providers:
            details = "* Vulnerable Providers:\n* {}".format(
                "\n* ".join(vulnerable_providers))
            details += "\n\nAn example of exploitation success:\n{}".format(
                example_result)

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

        return {"{}_result".format(self.name()): result}
Пример #28
0
    def run(self):
        result = {
            "title": "Application Allows Backups",
            "details": "",
            "severity": "Low",
            "report": False
        }

        # create manifest
        manifest_module = ManifestModule()
        manifest_module.decompiled_apk = self.decompiled_apk
        manifest = manifest_module.run()
        if "print" in manifest:
            return {"print": "Could not get the manifest"}

        manifest = manifest.popitem()[1]

        Log.info("Analysing application's manifest")

        if manifest.allow_backup():
            result.update({"report": True})

        return {
            "{}_result".format(self.name()): result
        }
Пример #29
0
    def run(self):
        Log.info("Dumping classes with otool")
        class_dump = otool_class_dump_to_dict(
            self.device.otool("-ov", self.binary)[0]) # stdout

        dump_name = self.binary.rsplit("/", 1)[-1].replace(" ", ".")
        result = {
            "{}_class_dump".format(dump_name.replace(".", "_")): class_dump
        }

        if hasattr(self, "output") and self.output:
            Log.info("Saving classes to file")
            dump_path = "{}/{}.class.dump".format(self.output, dump_name)

            # create output folder
            execute("mkdir -p {}".format(dump_path))

            save_class_dump(class_dump, dump_path)

            result.update({
                "{}_dump_path".format(dump_name.replace(".", "_")): dump_path,
                "print": "Dump saved in {}.".format(dump_path)
            })

        return result
Пример #30
0
    def run(self):
        Log.info("Starting application")

        if self.device.installed(self.identifier):

            self.device.start(self.identifier)

            return {"print": "Application {} started".format(self.identifier)}

        return {"print": "Application not installed"}