def run(self): if run_regex(self.file_path, WORLD_READABLE): self.issues.append(Issue(category=self.category, name="World readable file", severity=self.severity, description=WORLD_READABLE_DESCRIPTION, file_object=self.file_path)) if run_regex(self.file_path, WORLD_WRITEABLE): self.issues.append(Issue(category=self.category, name="World writeable file", severity=self.severity, description=WORLD_WRITEABLE_DESCRIPTION, file_object=self.file_path))
def run_coroutine(self): while True: _, class_ = (yield) if isinstance(class_, ClassCreator): if class_.type.name == "AllowAllHostnameVerifier": self.issues.append( Issue(category=self.category, name="Allow all hostname verifier used", severity=Severity.WARNING, description=ALLOW_ALL_HOSTNAME_VERIFIER_DESC, file_object=self.file_path)) elif class_.type.name == "NullHostNameVerifier" or class_.type.name == "NullHostnameVerifier": self.issues.append( Issue(category=self.category, name="Allow all hostname verifier used", severity=Severity.WARNING, description=ALLOW_ALL_HOSTNAME_VERIFIER_DESC, file_object=self.file_path)) elif isinstance(class_, MethodInvocation): if (class_.member == "setHostnameVerifier" and len(class_.arguments) == 1 and type(class_.arguments[0]) is MemberReference and class_.arguments[0].member == "ALLOW_ALL_HOSTNAME_VERIFIER"): self.issues.append( Issue(category=self.category, name="setHostnameVerifier set to ALLOW_ALL", severity=Severity.WARNING, description=ALLOW_ALL_HOSTNAME_VERIFIER_DESC, file_object=self.file_path, line_number=class_.position))
def run(self): permission_sections = self.manifest_xml.getElementsByTagName( "permission") for permission in permission_sections: try: protection_level = permission.attributes[ "android:protectionLevel"].value except KeyError: continue if protection_level in ("signature", "signatureOrSystem"): if self.min_sdk < 21: self.issues.append( Issue( category=self.category, severity=SIGNATURE_OR_SIGNATURE_OR_SYSTEM_SEVERITY, name=self.name, description= SIGNATURE_OR_SIGNATURE_OR_SYSTEM_DESCRIPTION, file_object=self.manifest_path)) elif protection_level == "dangerous": self.issues.append( Issue(category=self.category, severity=Severity.INFO, name=self.name, description=DANGEROUS_PERMISSION_DESCRIPTION, file_object=self.manifest_path))
def _add_issue(self, java_path): self.issues.append( Issue(category=self.category, severity=self.severity, name=self.name, description=self.description, file_object=java_path))
def run(self): if any("Context" in imp.path for imp in self.java_ast.imports): for result in run_regex2(self.file_path, CHECK_PERMISSION_REGEX): self.issues.append(Issue( category=self.category, severity=self.severity, name=self.name, description=self.description.format(used_permission="Check", recommended_permission="check"), file_object=self.file_path, line_number=result[1]) ) for result in run_regex2(self.file_path, ENFORCE_PERMISSION_REGEX): self.issues.append(Issue( category=self.category, severity=self.severity, name=self.name, description=self.description.format(used_permission="Enforce", recommended_permission="enforce"), file_object=self.file_path, line_number=result[1]) )
def _check_for_implicit_intents(self, parsed_tree): """ Checks for an invocation of one of the methods in `PENDING_INTENT_METHODS` and checks to see if an implicit Intent is passed to it. :param parsed_tree: `javalang.tree.parse` object """ # get all method invocations that are in PENDING_INTENT_METHODS pending_intent_invocations = ( method_invocation for _, method_invocation in parsed_tree.filter(MethodInvocation) if method_invocation.member in PENDING_INTENT_METHODS) for pending_intent_invocation in pending_intent_invocations: # iterate over every argument in the pending intent call, looking for a "new Intent()" for method_argument in pending_intent_invocation.arguments: for _, creation in method_argument.filter(ClassCreator): if len(creation.arguments) in ( 0, 1): # remove any intents created with arguments for _, reference_declaration in creation.filter( ReferenceType): if reference_declaration.name == "Intent": self.issues.append( Issue(category=self.category, severity=self.severity, name=self.name, description=self.description, file_object=self.current_file))
def run(self): if self.min_sdk < 9: self.issues.append( Issue(category=self.category, name="Tap Jacking possible", severity=Severity.VULNERABILITY, description=TAP_JACKING))
def _check_server_trusted(self, cert_method, current_file): """ Determines if the `checkServerTrusted` method is overriden with either no function body (defaults to allow) or if the body just returns. """ if not cert_method.body: self.issues.append(Issue(category=self.category, name="Empty certificate method", severity=self.severity, description=CHECK_SERVER_TRUSTED + MITM_DESCRIPTION, file_object=current_file, line_number=cert_method.position)) elif len(cert_method.body) == 1 and type(cert_method.body[0]) is ReturnStatement: self.issues.append(Issue(category=self.category, name="Empty (return) certificate method", severity=self.severity, description=CHECK_SERVER_TRUSTED + MITM_DESCRIPTION, file_object=current_file, line_number=cert_method.position))
def run_coroutine(self): while True: _, method_invocation = (yield) if not isinstance(method_invocation, MethodInvocation): continue if valid_set_method_bool(method_invocation, str_bool="true", method_name=self.java_method_name): self.issues.append(Issue(category=self.category, name=self.name, severity=self.severity, description=self.description, line_number=method_invocation.position, file_object=self.file_path))
def _process(self, tree, java_file): for _, method_invocation in tree.filter(MethodInvocation): if method_invocation.member == JAVA_DYNAMIC_BROADCAST_RECEIVER_METHOD and self.min_sdk < 14: self.issues.append(Issue( category=self.category, severity=self.severity, name=self.name, description=DYNAMIC_BROADCAST_RECEIVER_DESCRIPTION, file_object=java_file, line_number=method_invocation.position) )
def test_issue_json_list(): issue = Issue(category='Test', name='Test Issue', severity=Severity.VULNERABILITY, description='Test') json_output = issue_json([issue]) json_issue = json.loads(json_output) assert json_issue[0]['severity'] == issue.severity.name assert json_issue[0]['name'] == issue.name
def run(self): with open(self.manifest_path, "r") as manifest_file: for line_number, line in enumerate(manifest_file): if 'android:launchMode="singleTask"' in line: self.issues.append(Issue( category=self.category, severity=self.severity, name=self.name, description=self.description, file_object=self.manifest_path, line_number=line_number) )
def run_coroutine(self): while True: _, method_invocation = (yield) if not isinstance(method_invocation, MethodInvocation): continue if method_invocation.member == "loadDataWithBaseURL" and len(method_invocation.arguments) == 5: self.issues.append(Issue(category=self.category, name=self.name, severity=Severity.WARNING, description=self.description, line_number=method_invocation.position, file_object=self.file_path))
def run(self): for _, method_invocation in self.java_ast.filter(MethodInvocation): if method_invocation.qualifier == "Log" and method_invocation.member in ANDROID_LOGGING_METHODS: self.issues.append( Issue(category=self.category, severity=self.severity, name=self.name, description=self.description, file_object=self.file_path, line_number=method_invocation.position))
def run(self): if any("Context" in imp.path for imp in self.java_ast.imports): if re.search(CHECK_PERMISSION_REGEX, self.file_contents): self.issues.append( Issue(category=self.category, severity=self.severity, name=self.name, description=self.description.format( used_permission="Check", recommended_permission="check"), file_object=self.file_path)) if re.search(ENFORCE_PERMISSION_REGEX, self.file_contents): self.issues.append( Issue(category=self.category, severity=self.severity, name=self.name, description=self.description.format( used_permission="Enforce", recommended_permission="enforce"), file_object=self.file_path))
def run(self): results = run_regex2(self.file_path, WORLD_READABLE) for result in results: self.issues.append( Issue(category=self.category, name="World readable file", severity=self.severity, description=WORLD_READABLE_DESCRIPTION, file_object=self.file_path, line_number=result[1])) results = run_regex2(self.file_path, WORLD_WRITEABLE) for result in results: self.issues.append( Issue(category=self.category, name="World writeable file", severity=self.severity, description=WORLD_WRITEABLE_DESCRIPTION, file_object=self.file_path, line_number=result[1]))
def run(self): for _, method_invocation in self.java_ast.filter(MethodInvocation): if valid_set_method_bool(method_invocation, str_bool="true", method_name="setJavaScriptEnabled"): self.issues.append( Issue(category=self.category, name=self.name, severity=Severity.WARNING, description=self.description, line_number=method_invocation.position, file_object=self.file_path))
def run(self): application_sections = self.manifest_xml.getElementsByTagName( "application") for application in application_sections: if "android:allowBackup" in application.attributes.keys(): self.issues.append( Issue(category=self.category, severity=self.severity, name=self.name, description=self.description, file_object=self.manifest_path))
def run(self): for line_number, line in enumerate(self.file_contents.split("\n")): for word in line.split(): if re.search(API_KEY_REGEX, word) and not re.search( SPECIAL_CHARACTER_REGEX, word): self.issues.append( Issue(category=self.category, severity=self.severity, name=self.name, description=self.description, file_object=self.file_path, line_number=(line_number, 0)))
def _allow_all_hostname_verifier_created(self, tree, current_file): """ Checks for a class creation of `AllowAllHostnameVerifier`. :param tree: javalang parsed tree """ hostname_verifiers = [hostname_verifier for _, hostname_verifier in tree.filter(ClassCreator) if hostname_verifier.type.name == "AllowAllHostnameVerifier"] if hostname_verifiers: self.issues.append(Issue(category=self.category, name="Allow all hostname verifier used", severity=Severity.WARNING, description=ALLOW_ALL_HOSTNAME_VERIFIER_DESC, file_object=current_file))
def test_convert_severity(): issue = Issue(category='Test', name='Test Issue', severity='INFO', description='Test') assert issue.severity == Severity.INFO issue = Issue(category='Test', name='Test Issue', severity='VULNERABILITY', description='Test') assert issue.severity == Severity.VULNERABILITY issue = Issue(category='Test', name='Test Issue', severity='ERROR', description='Test') assert issue.severity == Severity.ERROR issue = Issue(category='Test', name='Test Issue', severity='WARNING', description='Test') assert issue.severity == Severity.WARNING issue = Issue(category='Test', name='Test Issue', severity='', description='Test') assert issue.severity == Severity.WARNING issue = Issue(category='Test', name='Test Issue', severity=4, description='Test') assert issue.severity == Severity.WARNING
def run_coroutine(self): while True: _, method_invocation = (yield) if valid_method_invocation(method_invocation, method_name=self.java_method_name, num_arguments=2): self.issues.append( Issue(category=self.category, name=self.name, severity=self.severity, description=self.description, line_number=method_invocation.position, file_object=self.file_path))
def run(self): for regex in PackagedPrivateKeys.PRIVATE_KEY_REGEXES: if run_regex(self.file_path, regex): log.debug( "It appears there is a private key embedded in your application: %s", self.file_path) description = "It appears there is a private key embedded in your application in the following file:" self.issues.append( Issue(self.category, self.name, self.severity, description, file_object=self.file_path))
def run_coroutine(self): while True: _, node = (yield) if isinstance(node, MethodDeclaration ) and node.name in INSECURE_FUNCTIONS_NAMES: self.issues.append( Issue(category=self.category, severity=self.severity, name=self.name, description=self.description, file_object=self.file_path, line_number=node.position))
def _on_received_ssl_error(self, cert_method, current_file): """ Determines if the `onReceivedSslError` method is overriden with a body of `handler.proceed()` which will drop SSL errors. """ if len(cert_method.body) == 1 and type(cert_method.body[0]) is StatementExpression: for _, method_invocation in cert_method.filter(MethodInvocation): if method_invocation.member == "proceed": self.issues.append(Issue(category=self.category, name="Unsafe implementation of onReceivedSslError", severity=self.severity, description=ON_RECEIVED_SSL_DESC, file_object=current_file, line_number=method_invocation.position))
def test_report_json_defaults(): report = Report() issue = Issue(category='Test', name='Test Issue', severity=Severity.VULNERABILITY, description='Test') report.issues.append(issue) report.generate(file_type='json') # We remove the issue we added to clean up after ourselves. report.issues.remove(issue) assert os.path.exists(os.path.join(DEFAULT_REPORT_PATH, 'report.json')) # We remove the report, to clean up after ourselves os.remove(os.path.join(DEFAULT_REPORT_PATH, 'report.json'))
def run(self): if self.min_sdk <= 16: for _, method_invocation in self.java_ast.filter(MethodInvocation): if valid_method_invocation(method_invocation, method_name=self.java_method_name, num_arguments=2): self.issues.append( Issue(category=self.category, name=self.name, severity=self.severity, description=self.description, line_number=method_invocation.position, file_object=self.file_path))
def run_coroutine(self): while True: _, method_invocation = (yield) if not isinstance(method_invocation, MethodInvocation): continue if method_invocation.member == JAVA_DYNAMIC_BROADCAST_RECEIVER_METHOD and self.min_sdk < 14: self.issues.append( Issue(category=self.category, severity=self.severity, name=self.name, description=DYNAMIC_BROADCAST_RECEIVER_DESCRIPTION, file_object=self.file_path, line_number=method_invocation.position))
def run(self): method_invocations = self.java_ast.filter(javalang.tree.MethodInvocation) for _, method_invocation_node in method_invocations: try: method_name = method_invocation_node.member encryption_type = method_invocation_node.arguments[0].value qualifier = method_invocation_node.qualifier # the thing that getInstance is called on if method_name == 'getInstance' and qualifier == 'Cipher' and re.search(r'.*/ECB/.*', encryption_type): description = "getInstance should not be called with ECB as the cipher mode, as it is insecure." self.issues.append( Issue(self.category, self.name, self.severity, description, file_object=self.file_path)) except Exception: continue
def run(self): for _, class_declaration in self.java_ast.filter(ClassDeclaration): for _, method_declaration_in_class in class_declaration.filter( MethodDeclaration): if method_declaration_in_class.name in INSECURE_FUNCTIONS_NAMES: self.issues.append( Issue( category=self.category, severity=self.severity, name=self.name, description=self.description, file_object=self.file_path, line_number=method_declaration_in_class.position))