Example #1
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)
Example #2
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)
Example #3
0
    def target(self, queue):
        results = []
        #TODO: add documentation for available API calls. Sample shown below.
        # Here, we want to scan all decompiled files to see if any file contains the text "API_KEY"
        possibleFiles = common.text_scan(common.java_files, r'API_KEY')
        count = 0
        for f in possibleFiles:
            count += 1
            # The following call generates the progress bar in the terminal output
            pub.sendMessage('progress', bar=self.getName(), percent=round(count*100/len(possibleFiles)))

            # Mostly for logging. This goes in the log file generated under /logs
            common.logger.debug("Text found, " + str(f))

            # This will put individual results of the plugin scan in the HTML report.
            issue = ReportIssue()
            issue.setCategory(ExploitType.PLUGIN)
            issue.setDetails("The string 'API_KEY' appears in the file: %s\n%s" % (f[1], str(f[0])))
            issue.setFile(str(f[1]))
            issue.setSeverity(Severity.VULNERABILITY)
            results.append(issue)

            # This puts individual results of the plugin scan in the terminal output.
            issue = terminalPrint()
            issue.setLevel(Severity.VULNERABILITY)
            issue.setData("The string 'API_KEY' appears in the file: %s\n%s" % (f[1], str(f[0])))
            results.append(issue)

        # This is required to send the complete list of results (including the ones to be printed on terminal as well as
        # issues to be printed in tht HTML report) back to the main thread.
        queue.put(results)
Example #4
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)
Example #5
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)
Example #6
0
def find_key_files(results):
	'''	PackagedPrivateKey
	------------------
	Summary: Packaged private key

	Priority: 8 / 10
	Severity: Fatal
	Category: Security

	In general, you should not package private key files inside your app.
	'''
	if len(common.keyFiles)>0:
		possibleKeyFiles=common.text_scan(common.keyFiles,r'PRIVATE\sKEY')
		if len(possibleKeyFiles)>0:
			for f in possibleKeyFiles:
				common.logger.debug("It appears there is a private key embedded in your application: " + str(f))
				issue = ReportIssue()
				issue.setCategory(ExploitType.CRYPTO)
				issue.setDetails("It appears there is a private key embedded in your application in the following file:")
				issue.setFile(str(f))
				issue.setSeverity(Severity.VULNERABILITY)
				results.append(issue)

				issue = terminalPrint()
				issue.setLevel(Severity.VULNERABILITY)
				issue.setData("It appears there is a private key embedded in your application in the following file:")
				results.append(issue)
	return
Example #7
0
def find_key_files(results):
    '''	PackagedPrivateKey
	------------------
	Summary: Packaged private key

	Priority: 8 / 10
	Severity: Fatal
	Category: Security

	In general, you should not package private key files inside your app.
	'''
    if len(common.keyFiles) > 0:
        possibleKeyFiles = common.text_scan(common.keyFiles, r'PRIVATE\sKEY')
        if len(possibleKeyFiles) > 0:
            for f in possibleKeyFiles:
                common.logger.debug(
                    "It appears there is a private key embedded in your application: "
                    + str(f))
                issue = ReportIssue()
                issue.setCategory(ExploitType.CRYPTO)
                issue.setDetails(
                    "It appears there is a private key embedded in your application in the following file:"
                )
                issue.setFile(str(f))
                issue.setSeverity(Severity.VULNERABILITY)
                results.append(issue)

                issue = terminalPrint()
                issue.setLevel(Severity.VULNERABILITY)
                issue.setData(
                    "It appears there is a private key embedded in your application in the following file:"
                )
                results.append(issue)
    return
Example #8
0
    def target(self, queue):
        results = []
        possibleFiles = common.text_scan(common.java_files, r'API_KEY')
        count = 0
        for f in possibleFiles:
            count += 1
            pub.sendMessage('progress',
                            bar=self.getName(),
                            percent=round(count * 100 / len(possibleFiles)))
            common.logger.debug("Text found, " + str(f))
            issue = ReportIssue()
            issue.setCategory(ExploitType.PLUGIN)
            issue.setDetails(
                "The string 'API_KEY' appears in the file: %s\n%s" %
                (f[1], str(f[0])))
            issue.setFile(str(f[1]))
            issue.setSeverity(Severity.VULNERABILITY)
            results.append(issue)

            issue = terminalPrint()
            issue.setLevel(Severity.VULNERABILITY)
            issue.setData("The string 'API_KEY' appears in the file: %s\n%s" %
                          (f[1], str(f[0])))
            results.append(issue)

        queue.put(results)
Example #9
0
    def target(self, queue):
        results = []
        #TODO: add documentation for available API calls. Sample shown below.
        # Here, we want to scan all decompiled files to see if any file contains the text "pass"
        possibleFiles = common.text_scan(common.java_files, r'pass')
        count = 0
        for f in possibleFiles:
            count += 1
            # The following call generates the progress bar in the terminal output
            pub.sendMessage('progress', bar=self.getName(), percent=round(count*100/len(possibleFiles)))

            # Mostly for logging. This goes in the log file generated under /logs
            common.logger.debug("Text found, " + str(f))
            issue = ReportIssue()

            # This will put individual results of the plugin scan in the HTML report.
            issue.setCategory(ExploitType.PLUGIN)
            issue.setDetails("The string 'pass' appears in the file: %s\n%s" % (f[1], str(f[0])))
            issue.setFile(str(f[1]))
            issue.setSeverity(Severity.VULNERABILITY)
            results.append(issue)

            # This puts individual results of the plugin scan in the terminal output.
            issue = terminalPrint()
            issue.setLevel(Severity.VULNERABILITY)
            issue.setData("The string 'pass' appears in the file: %s\n%s" % (f[1], str(f[0])))
            results.append(issue)

        # This is required to send the complete list of results (including the ones to be printed on terminal as well as
        # issues to be printed in tht HTML report) back to the main thread.
        queue.put(results)
Example #10
0
def find_intent_files():
    """
	Find all files declaring or using intents in the application
	"""
    common.logger.info("Attempting to trace Intent Sources to Sinks")
    int_files = []
    int_dec_list = []
    int_dec_list.append([])
    int_rex = r'import\sandroid\.content\.Intent'
    # This syntax is deprecated
    int_assign_rex1 = r'Intent\s*[A-Za-z0-9_$]+\s*[=;]\s+getIntent\('
    int_assign_rex2 = r'[A-Za-z0-9_$]+\s*[=;]\s*Intent\.parseUri\('
    int_assign_rex3 = r'Intent\s*[A-Za-z0-9_$]+\s*[=;]\s*new\s+Intent\('
    int_files += common.text_scan(common.java_files, int_rex)
    for i in int_files:
        if len(i) > 0:
            tmp = [i[1]]
            int_dec_list += common.text_scan(tmp, int_assign_rex1)
            int_dec_list += common.text_scan(tmp, int_assign_rex2)
            int_dec_list += common.text_scan(tmp, int_assign_rex3)
    common.logger.info("Intent Declarations:")
    int_dec_list = filter(None, int_dec_list)
    for d in int_dec_list:
        if len(d) > 0:
            d[0] = re.sub(r'\s*[=;]\s*new\s*Intent\(.*', '', str(d[0]))
            d[0] = re.sub(r'(final)?\s*Intent\s+', '', str(d[0]))
            d[0] = re.sub(r'[=;]\s*getIntent\(.*', '', str(d[0]))
            d[0] = re.sub(r'\'', '', str(d[0]))
            d[0] = re.sub(r'\"', '', str(d[0]))
            d[0] = re.sub(r'\s+', '', str(d[0]))
            d[0] = re.sub(r'\[', '', str(d[0]))
            d[0] = re.sub(r'\\\\\t', '', str(d[0]))
            d[0] = re.sub(r'\\\t', '', str(d[0]))
            d[0] = re.sub(r'\\t', '', str(d[0]))
            d[0] = str(d[0]).strip('\t\n\r')
    common.logger.info(int_dec_list)
    return
Example #11
0
def find_intent_files():
    """
	Find all files declaring or using intents in the application
	"""
    common.logger.info("Attempting to trace Intent Sources to Sinks")
    int_files = []
    int_dec_list = []
    int_dec_list.append([])
    int_rex = r'import\sandroid\.content\.Intent'
    #This syntax is deprecated
    int_assign_rex1 = r'Intent\s*[A-Za-z0-9_$]+\s*[=;]\s+getIntent\('
    int_assign_rex2 = r'[A-Za-z0-9_$]+\s*[=;]\s*Intent\.parseUri\('
    int_assign_rex3 = r'Intent\s*[A-Za-z0-9_$]+\s*[=;]\s*new\s+Intent\('
    int_files += common.text_scan(common.java_files, int_rex)
    for i in int_files:
        if len(i) > 0:
            tmp = [i[1]]
            int_dec_list += common.text_scan(tmp, int_assign_rex1)
            int_dec_list += common.text_scan(tmp, int_assign_rex2)
            int_dec_list += common.text_scan(tmp, int_assign_rex3)
    common.logger.info("Intent Declarations:")
    int_dec_list = filter(None, int_dec_list)
    for d in int_dec_list:
        if len(d) > 0:
            d[0] = re.sub(r'\s*[=;]\s*new\s*Intent\(.*', '', str(d[0]))
            d[0] = re.sub(r'(final)?\s*Intent\s+', '', str(d[0]))
            d[0] = re.sub(r'[=;]\s*getIntent\(.*', '', str(d[0]))
            d[0] = re.sub(r'\'', '', str(d[0]))
            d[0] = re.sub(r'\"', '', str(d[0]))
            d[0] = re.sub(r'\s+', '', str(d[0]))
            d[0] = re.sub(r'\[', '', str(d[0]))
            d[0] = re.sub(r'\\\\\t', '', str(d[0]))
            d[0] = re.sub(r'\\\t', '', str(d[0]))
            d[0] = re.sub(r'\\t', '', str(d[0]))
            d[0] = str(d[0]).strip('\t\n\r')
    common.logger.info(int_dec_list)
    return
Example #12
0
def find_gradle():
    version = 0
    files = []
    for (dirpath, dirname, filenames) in os.walk(common.sourceDirectory):
        for filename in filenames:
            if filename == 'build.gradle':
                files.append(os.path.join(dirpath, filename))
    if len(files) > 0:
        matches = common.text_scan(files, r'def\s_compileSdkVersion\s*=\s*[0-9]+')
        # TODO - fix this so we don't have to account for the empty first element
        # We skip it if there are multiple build.gradle files, since manual input is unavoidable at that point
        if len(matches) == 2:
            for m in matches:
                if len(m) > 0:
                    version = re.compile('\d+')
                    version = version.findall(str(m[0]))[0]
    return version
Example #13
0
def findGradle():
	version=0
	files=[]
	for (dirpath,dirname, filenames) in os.walk(common.sourceDirectory):
		for filename in filenames:
			if filename=='build.gradle':
				files.append(os.path.join(dirpath,filename))
	if len(files)>0:
		matches=common.text_scan(files,r'def\s_compileSdkVersion\s*=\s*[0-9]+')
		#TODO - fix this so we don't have to account for the empty first element
		#We skip it if there are multiple build.gradle files, since manual input is unavoidable at that point
		if len(matches)==2:
			for m in matches:
				if len(m)>0:
					version=re.compile('\d+')
					version=version.findall(str(m[0]))[0]
	return version
Example #14
0
    def target(self, queue):
        results = []
        possibleFiles = common.text_scan(common.java_files, r'pass')
        count = 0
        for f in possibleFiles:
            count += 1
            pub.sendMessage('progress', bar=self.getName(), percent=round(count*100/len(possibleFiles)))
            common.logger.debug("Text found, " + str(f))
            issue = ReportIssue()
            issue.setCategory(ExploitType.PLUGIN)
            issue.setDetails("The string 'pass' appears in the file: %s\n%s" % (f[1], str(f[0])))
            issue.setFile(str(f[1]))
            issue.setSeverity(Severity.VULNERABILITY)
            results.append(issue)

            issue = terminalPrint()
            issue.setLevel(Severity.VULNERABILITY)
            issue.setData("The string 'pass' appears in the file: %s\n%s" % (f[1], str(f[0])))
            results.append(issue)
        
        
        queue.put(results)
Example #15
0
File: qark.py Project: zhouat/qark
        except Exception as e:
            common.logger.error("Unable to check for exported Preference Activities: " + str(e))
    '''
    #########################
    #Look for TapJacking vulnerabilities
    #Native protection was added in API v. 9, so previous likely vulnerable
    if common.minSdkVersion >8:
        common.logger.debug("Beginning TapJacking testing")
        findTapJacking.start(common.sourceDirectory)
    else:
        common.logger.log(common.VULNERABILITY_LEVEL,"Since the minSdkVersion is less that 9, it is likely this application is vulnerable to TapJacking. QARK made no attempt to confirm, as the protection would have to be custom code, which is difficult for QARK to examine and understand properly. This vulnerability allows a malicious application to lay on top of this app, while letting the key strokes pass through to the application below. This can cause users to take unwanted actions, within the victim application, similar to Clickjacking on websites. Please select the appropriate options in the exploitation menus to verify manually using QARK's exploit APK. Note: The QARK proof-of-concept is transparent, but in real-world attacks, it would likely not be. This is done solely to aid in testing. For more information: https://media.blackhat.com/ad-12/Niemietz/bh-ad-12-androidmarcus_niemietz-WP.pdf")


    ###########
    #Look for Content Provider issues
    if len(common.text_scan(common.java_files,cp_imp_rex)) > 1:
        common.logger.info("Content Providers appear to be in use, locating...")
        cp_dec_list=contentProvider.find_content_providers()
        cp_dec_list=filter(None,cp_dec_list)
        cp_dec_list=common.dedup(cp_dec_list)

        common.logger.info("FOUND " + str(len(cp_dec_list)) + " CONTENTPROVIDERS:")
        for p in cp_dec_list:
            common.logger.info(str(p))

        query_rex=r'\.query\(.*\)'
        update_rex=r'\.update\(.*\)'
        delete_rex=r'\.delete\(.*\)'
        insert_rex=r'\.insert\(.*\)'
        #TODO - Add SQLi checks
        #VERY LAME SQL INJECTION DETECTION (GUESSING)
Example #16
0
def find_extras(stub_file_name, path):
    """
	Find all extras given a filename
	"""
    # TODO - This needs to be gutted and re-writtten
    extras = []
    filename = re.search(r'\w+$', stub_file_name)
    filename = filename.group()
    fname = common.grep(path, r'' + str(filename) + '\.java')
    rextras = []
    rextras.append(r'getExtras\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getStringExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getIntExtra\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getIntArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getFloatExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getFloatArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getDoubleExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getDoubleArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getCharExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getCharArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getByteExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getByteArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getBundleExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getBooleanExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getBooleanArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getCharSequenceArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getCharSequenceArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getCharSequenceExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getInterArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getLongArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getLongExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getParcelableArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getParcelableArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getParcelableExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getSeriablizableExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getShortArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getShortExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getStringArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
    rextras.append(r'getStringArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+')
    # These are not necessarily Intent extras, but may contain them
    rextras.append(r'getString\(\s*[0-9A-Za-z_\"\'.]+')

    # TODO add data types to the extras, so we can provide better suggestions
    if len(fname) > 0:
        x_tmp = []
        x_tmp.append([])
        for r in rextras:
            x_tmp = common.text_scan(fname, r)
            for m in x_tmp:
                if len(m) > 0:
                    i = 0
                    for l in m:
                        if type(l) is list:
                            sigh = []
                            for s in l:
                                sigh.append(re.sub(r'.*\(', '', str(s)))
                                sigh[i] = re.sub(r'\).*', '', sigh[i])
                                sigh[i] = re.sub(r'\s*,.*', '', sigh[i])
                                extras += sigh
                                i += 1
                extras = common.dedup(extras)
        if len(extras) < 1:
            common.logger.debug("No extras found in " + str(fname[0]) + " to suggest.\n")
            common.parsingerrors.add(str(fname[0]))
    else:
        # BUG - seems like a flow can come here without the fname; Ex: Flagship S - 4
        common.logger.error("Sorry, we could not find a filename while looking for extras\n")
    # Trying to get rid of empty first element
    return extras
Example #17
0
def find_content_providers():
    """
    Find all content providers and return the list
    """
    cp_list = common.find_ext('ContentProvider')

    growing = 1
    # TODO - This is ugly and needs to be re-written
    # The intention here is to loop endlessly until all extensions are found
    while growing:
        cp_list_count_old = len(cp_list)
        cp_list += common.tree(cp_list)
        if len(cp_list) == cp_list_count_old:
            growing = 0

    cp_list.append(['ContentProvider', ''])

    cp_decs = []
    cp_decs.append([])
    for x in cp_list:
        if len(x) > 0:
            tmp = r'' + re.escape(str(x[0])) + r'\s\w+[;=]'
            cp_decs += common.text_scan(common.java_files, tmp)
            tmp = r'(private .*|protected.*)' + re.escape(str(
                x[0])) + r'\s\w+;'
            cp_decs += common.text_scan(common.java_files, tmp)
            tmp = r'\w+\s[;=]\snew\s' + re.escape(str(x[0])) + r'\('
            cp_decs += common.text_scan(common.java_files, tmp)
            tmp = r'\(.*' + re.escape(
                str(x[0])
            ) + r'\s\w+.*\)'  # Need to ensure this is working properly

    tmp_list2 = []
    tmp_list2.append([])
    for z in cp_decs:
        if len(z) > 0:
            # conditional declarations will cause conditional positives
            # BUG sometimes Z[0] is a list, rather than just a list element. Need to separate, remove and re-parse
            if (len(z[0]) > 1 and not isinstance(z[0], str)):
                for x in z[0]:
                    foo = [x, z[1]]
                    tmp_list2.append(foo)
                cp_decs.pop()
                continue
            else:
                tmp_list2.append(z)
        else:
            tmp_list2.append(z)

    tmp_list2 = filter(None, tmp_list2)

    for y in tmp_list2:
        if len(y) > 0:
            y[0] = re.sub(r';\\n', '', str(y[0]).strip('[]\''))
            y[0] = re.sub(r'\\t*', '', y[0])
            y[0] = re.sub(r'\s*private\b', '', y[0])
            y[0] = re.sub(r'\s*protected\b', '', y[0])
            y[0] = re.sub(r'\s*static\b', '', y[0])
            y[0] = re.sub(r'^\s*ContentProvider\b', '', y[0])
            y[0] = re.sub(r'\s*[;=]\s*new\sContentProvider\s.*', '', y[0])
            y[0] = re.sub(r'\s*[;=]\s*new\s\w+\(.*\)', '', y[0])
            y[0] = re.sub(r'^\s*', '', y[0])
            y[0] = re.sub(r'\s*$', '', y[0])
            y[0] = re.sub(r'^\w+\s', '', y[0])
            y[0] = re.sub(r';$', '', y[0])
            # remove whitespace
            y[0] = y[0].strip(' \t\r\n')

    tmp_list2 = common.dedup(tmp_list2)
    return tmp_list2
Example #18
0
def find_webviews():
    """
    Finds all webviews in the decompiled source code
    """
    #1. Look for classes that extend WebView
    #Find classes that extend Web View
    wv_list=find_ext('WebView')
    #2. Look for classes that extend classes that extend WebView
    while len(common.tree(wv_list)) > 1:
        wv_list+=common.tree(wv_list)

    wv_list.append(['WebView','']) 
    #3. Cleanup?
    #4. Look for all declaration of WebViews using normal and extended class names
    #BUG sometimes multiple declarations are coming back for z[0], need to figure out what is going on there
    #Currently there may be false negatives
    #BUG - Need to review this for optional/multiple spaces
    wv_decs=[]
    wv_decs.append([])
    for x in wv_list:
        if len(x)>0:
            tmp=r''+re.escape(str(x[0]))+r'\s\w+[;=]'
            wv_decs+=common.text_scan(common.java_files,tmp)
            tmp=r'(private .*|protected.*)'+ re.escape(str(x[0]))+r'\s\w+;'
            wv_decs+=common.text_scan(common.java_files,tmp)
            tmp=r'\w+\s[;=]\snew\s'+re.escape(str(x[0]))+r'\('
            wv_decs+=common.text_scan(common.java_files,tmp)
            tmp=r'\(.*'+re.escape(str(x[0]))+r'\s\w+.*\)' # Need to ensure this is working properly

    tmp_list2=[]
    tmp_list2.append([])
    for z in wv_decs:
        if len(z)>0:
            #conditional declarations will cause conditional positives
            #BUG sometimes Z[0] is a list, rather than just a list element. Need to separate, remove and re-parse
            if (len(z[0])>1 and not isinstance(z[0],str)):
                for x in z[0]:
                    foo=[x,z[1]]
                    tmp_list2.append(foo)
                wv_decs.pop()
                continue
            else:
                tmp_list2.append(z)
        else:
            tmp_list2.append(z)

    tmp_list2=filter(None,tmp_list2)

    for y in tmp_list2:
        if len(y)>0:
            y[0]=re.sub(r';\\n','',str(y[0]).strip('[]\''))
            y[0]=re.sub(r'\\t*','',y[0])
            y[0]=re.sub(r'\s*private\b','',y[0])
            y[0]=re.sub(r'\s*protected\b','',y[0])
            y[0]=re.sub(r'\s*static\b','',y[0])
            y[0]=re.sub(r'^\s*WebView\b','',y[0])
            y[0]=re.sub(r'\s*[;=]\s*new\sWebView\s.*','',y[0])
            y[0]=re.sub(r'\s*[;=]\s*new\s\w+\(.*\)','',y[0])
            y[0]=re.sub(r'^\s*','',y[0])
            y[0]=re.sub(r'\s*$','',y[0])
            y[0]=re.sub(r'^\w+\s','',y[0])
            y[0]=re.sub(r';$','',y[0])
            #remove whitespace
            y[0]=y[0].strip(' \t\r\n')

    tmp_list2=common.dedup(tmp_list2)

    return tmp_list2
Example #19
0
def find_webviews():
    """
    Finds all webviews in the decompiled source code
    """
    #1. Look for classes that extend WebView
    #Find classes that extend Web View
    wv_list = find_ext('WebView')
    #2. Look for classes that extend classes that extend WebView
    while len(common.tree(wv_list)) > 1:
        wv_list += common.tree(wv_list)

    wv_list.append(['WebView', ''])
    #3. Cleanup?
    #4. Look for all declaration of WebViews using normal and extended class names
    #BUG sometimes multiple declarations are coming back for z[0], need to figure out what is going on there
    #Currently there may be false negatives
    #BUG - Need to review this for optional/multiple spaces
    wv_decs = []
    wv_decs.append([])
    for x in wv_list:
        if len(x) > 0:
            tmp = r'' + re.escape(str(x[0])) + r'\s\w+[;=]'
            wv_decs += common.text_scan(common.java_files, tmp)
            tmp = r'(private .*|protected.*)' + re.escape(str(
                x[0])) + r'\s\w+;'
            wv_decs += common.text_scan(common.java_files, tmp)
            tmp = r'\w+\s[;=]\snew\s' + re.escape(str(x[0])) + r'\('
            wv_decs += common.text_scan(common.java_files, tmp)
            tmp = r'\(.*' + re.escape(
                str(x[0])
            ) + r'\s\w+.*\)'  # Need to ensure this is working properly

    tmp_list2 = []
    tmp_list2.append([])
    for z in wv_decs:
        if len(z) > 0:
            #conditional declarations will cause conditional positives
            #BUG sometimes Z[0] is a list, rather than just a list element. Need to separate, remove and re-parse
            if (len(z[0]) > 1 and not isinstance(z[0], str)):
                for x in z[0]:
                    foo = [x, z[1]]
                    tmp_list2.append(foo)
                wv_decs.pop()
                continue
            else:
                tmp_list2.append(z)
        else:
            tmp_list2.append(z)

    tmp_list2 = filter(None, tmp_list2)

    for y in tmp_list2:
        if len(y) > 0:
            y[0] = re.sub(r';\\n', '', str(y[0]).strip('[]\''))
            y[0] = re.sub(r'\\t*', '', y[0])
            y[0] = re.sub(r'\s*private\b', '', y[0])
            y[0] = re.sub(r'\s*protected\b', '', y[0])
            y[0] = re.sub(r'\s*static\b', '', y[0])
            y[0] = re.sub(r'^\s*WebView\b', '', y[0])
            y[0] = re.sub(r'\s*[;=]\s*new\sWebView\s.*', '', y[0])
            y[0] = re.sub(r'\s*[;=]\s*new\s\w+\(.*\)', '', y[0])
            y[0] = re.sub(r'^\s*', '', y[0])
            y[0] = re.sub(r'\s*$', '', y[0])
            y[0] = re.sub(r'^\w+\s', '', y[0])
            y[0] = re.sub(r';$', '', y[0])
            #remove whitespace
            y[0] = y[0].strip(' \t\r\n')

    tmp_list2 = common.dedup(tmp_list2)

    return tmp_list2
Example #20
0
def find_extras(stub_file_name,path):
	"""
	Find all extras given a filename
	"""
	#TODO - This needs to be gutted and re-writtten
	extras=[]
	filename=re.search(r'\w+$',stub_file_name)
	filename=filename.group()
	fname=common.grep(path,r''+str(filename)+'\.java')
	rextras=[]
	rextras.append(r'getExtras\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getStringExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getIntExtra\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getIntArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getFloatExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getFloatArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getDoubleExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getDoubleArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getCharExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getCharArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getByteExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getByteArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getBundleExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getBooleanExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getBooleanArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getCharSequenceArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getCharSequenceArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getCharSequenceExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getInterArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getLongArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getLongExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getParcelableArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getParcelableArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getParcelableExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getSeriablizableExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getShortArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getShortExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getStringArrayExtra\(\s*[0-9A-Za-z_\"\'.]+')
	rextras.append(r'getStringArrayListExtra\(\s*[0-9A-Za-z_\"\'.]+')
	#These are not necessarily Intent extras, but may contain them
	rextras.append(r'getString\(\s*[0-9A-Za-z_\"\'.]+')

	#TODO add data types to the extras, so we can provide better suggestions
	if len(fname)>0:
		x_tmp=[]
		x_tmp.append([])
		for r in rextras:
			x_tmp=common.text_scan(fname,r)
			for m in x_tmp:
				if len(m)>0:
					i=0
					for l in m:
						if type(l) is list:
							sigh=[]
							for s in l:
								sigh.append(re.sub(r'.*\(','',str(s)))
								sigh[i]=re.sub(r'\).*','',sigh[i])
								sigh[i]=re.sub(r'\s*,.*','',sigh[i])
								extras+=sigh
								i+=1
				extras=common.dedup(extras)
		if len(extras)<1:
			common.logger.debug("No extras found in " + str(fname[0]) + " to suggest.\n")
			common.parsingerrors.add(str(fname[0]))
	else:
		#BUG - seems like a flow can come here without the fname; Ex: Flagship S - 4
		common.logger.error("Sorry, we could not find a filename while looking for extras\n")
	#Trying to get rid of empty first element
	return extras
Example #21
0
	except Exception as e:
		common.logger.error("Unable to check for exported Preference Activities: " + str(e))
'''
#########################
#Look for TapJacking vulnerabilities
#Native protection was added in API v. 9, so previous likely vulnerable
if common.minSdkVersion >8:
	common.logger.debug("Beginning TapJacking testing")
	findTapJacking.start(common.sourceDirectory)
else:
	common.logger.log(common.VULNERABILITY_LEVEL,"Since the minSdkVersion is less that 9, it is likely this application is vulnerable to TapJacking. QARK made no attempt to confirm, as the protection would have to be custom code, which is difficult for QARK to examine and understand properly. This vulnerability allows a malicious application to lay on top of this app, while letting the key strokes pass through to the application below. This can cause users to take unwanted actions, within the victim application, similar to Clickjacking on websites. Please select the appropriate options in the exploitation menus to verify manually using QARK's exploit APK. Note: The QARK proof-of-concept is transparent, but in real-world attacks, it would likely not be. This is done solely to aid in testing. For more information: https://media.blackhat.com/ad-12/Niemietz/bh-ad-12-androidmarcus_niemietz-WP.pdf")


###########
#Look for Content Provider issues
if len(common.text_scan(common.java_files,cp_imp_rex)) > 1:
	common.logger.info("Content Providers appear to be in use, locating...")
	cp_dec_list=contentProvider.find_content_providers()
	cp_dec_list=filter(None,cp_dec_list)
	cp_dec_list=common.dedup(cp_dec_list)

	common.logger.info("FOUND " + str(len(cp_dec_list)) + " CONTENTPROVIDERS:")
	for p in cp_dec_list:
		common.logger.info(str(p))

	query_rex=r'\.query\(.*\)'
	update_rex=r'\.update\(.*\)'
	delete_rex=r'\.delete\(.*\)'
	insert_rex=r'\.insert\(.*\)'
	#TODO - Add SQLi checks
	#VERY LAME SQL INJECTION DETECTION (GUESSING)
Example #22
0
def find_content_providers():
    """
    Find all content providers and return the list
    """
    cp_list = common.find_ext('ContentProvider')

    growing = 1
    # TODO - This is ugly and needs to be re-written
    # The intention here is to loop endlessly until all extensions are found
    while growing:
        cp_list_count_old = len(cp_list)
        cp_list += common.tree(cp_list)
        if len(cp_list) == cp_list_count_old:
            growing = 0

    cp_list.append(['ContentProvider', ''])

    cp_decs = []
    cp_decs.append([])
    for x in cp_list:
        if len(x) > 0:
            tmp = r'' + re.escape(str(x[0])) + r'\s\w+[;=]'
            cp_decs += common.text_scan(common.java_files, tmp)
            tmp = r'(private .*|protected.*)' + re.escape(str(x[0])) + r'\s\w+;'
            cp_decs += common.text_scan(common.java_files, tmp)
            tmp = r'\w+\s[;=]\snew\s' + re.escape(str(x[0])) + r'\('
            cp_decs += common.text_scan(common.java_files, tmp)
            tmp = r'\(.*' + re.escape(str(x[0])) + r'\s\w+.*\)'  # Need to ensure this is working properly

    tmp_list2 = []
    tmp_list2.append([])
    for z in cp_decs:
        if len(z) > 0:
            # conditional declarations will cause conditional positives
            # BUG sometimes Z[0] is a list, rather than just a list element. Need to separate, remove and re-parse
            if (len(z[0]) > 1 and not isinstance(z[0], str)):
                for x in z[0]:
                    foo = [x, z[1]]
                    tmp_list2.append(foo)
                cp_decs.pop()
                continue
            else:
                tmp_list2.append(z)
        else:
            tmp_list2.append(z)

    tmp_list2 = filter(None, tmp_list2)

    for y in tmp_list2:
        if len(y) > 0:
            y[0] = re.sub(r';\\n', '', str(y[0]).strip('[]\''))
            y[0] = re.sub(r'\\t*', '', y[0])
            y[0] = re.sub(r'\s*private\b', '', y[0])
            y[0] = re.sub(r'\s*protected\b', '', y[0])
            y[0] = re.sub(r'\s*static\b', '', y[0])
            y[0] = re.sub(r'^\s*ContentProvider\b', '', y[0])
            y[0] = re.sub(r'\s*[;=]\s*new\sContentProvider\s.*', '', y[0])
            y[0] = re.sub(r'\s*[;=]\s*new\s\w+\(.*\)', '', y[0])
            y[0] = re.sub(r'^\s*', '', y[0])
            y[0] = re.sub(r'\s*$', '', y[0])
            y[0] = re.sub(r'^\w+\s', '', y[0])
            y[0] = re.sub(r';$', '', y[0])
            # remove whitespace
            y[0] = y[0].strip(' \t\r\n')

    tmp_list2 = common.dedup(tmp_list2)
    return tmp_list2