def checkWebviewSSLErrorBypass(self): grep = Grep("Landroid\/webkit\/SslErrorHandler;->proceed\(\)V", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) self.vulnerableWebViewSSLErrorBypass.extend(res)
def determineContentProviderPathTraversal(self, provider): if provider.startswith("."): providerName = self.apk.apk.get_package() + provider else: providerName = provider providerName = providerName.replace("$", "\$").replace(".", "/") # Check if provider location was previously found if provider in self.providerLocations: res = [self.providerLocations[provider]] else: grep = Grep("\.class .* L" + providerName, self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: self.providerLocations[provider] = location method = self.getMethod( r"\.method public openFile\(Landroid\/net\/Uri;Ljava\/lang\/String;\)Landroid\/os\/ParcelFileDescriptor;", r"\.end method", location) if not method: continue indexList = self.findInstructionIndex( method, "Ljava\/io\/File;->getCanonicalPath\(\)") if not indexList: # If file is being loaded with getCanonicalPath(), then it is probably safe self.vulnerableContentProvidersPathTraversalLocations.append( location)
def determineContentProviderSQLi(self, provider): if provider.startswith("."): providerName = self.apk.apk.get_package() + provider else: providerName = provider providerName = providerName.replace("$", "\$").replace(".", "/") grep = Grep("\.class .* L" + providerName, self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: self.providerLocations[provider] = location method = self.getMethod( r"\.method public query\(Landroid\/net\/Uri;\[Ljava\/lang\/String;Ljava\/lang\/String;\[Ljava\/lang\/String;Ljava\/lang\/String;\)Landroid\/database\/Cursor;", r"\.end method", location) if not method: continue indexList = self.findInstructionIndex( method, "invoke-virtual(.*) {(.*)}, Landroid\/database\/sqlite\/SQLiteDatabase;->query" ) indexList.extend( self.findInstructionIndex( method, "invoke-virtual(.*) {(.*)}, Landroid\/database\/sqlite\/SQLiteQueryBuilder;->query\(Landroid/database/sqlite/SQLiteDatabase;" )) if indexList and not self.findInstructionIndex(method, "\?"): self.vulnerableContentProvidersSQLiLocations.append(location)
def findEncryptionFunctions(self): grep = Grep( "invoke-virtual {(.*)}, Ljavax\/crypto\/Cipher;->init\(ILjava\/security\/Key", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: if "org/bouncycastle" in location: continue instructions = self.getFileContent(location) indexList = self.findInstructionIndex( instructions, "Ljavax/crypto/Cipher;->init\(ILjava/security/Key") for index in indexList: registers = self.findRegistersPassedToFunction( instructions[index]) if self.findRegisterAssignedValueFromIndexBackwards( instructions, registers[1], index) == "0x1": self.encryptionFunctionsLocation.append(location) elif self.findRegisterAssignedValueFromIndexBackwards( instructions, registers[1], index) == "0x2": self.decryptionFunctionsLocation.append(location) else: self.undeterminedCryptographicFunctionsLocation.append( location)
def findCustomChecks(self, checks): for check in checks: self.customChecksLocations[check[0]] = [] grep = Grep(check[1]) res = grep.check_directories(self.smaliPaths) self.customChecksLocations[check[0]].extend(res)
def findWebViewLoadUrlUsage(self): grep = Grep( "Landroid\/webkit\/WebView;->loadUrl\(Ljava\/lang\/String;\)V", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) self.webViewLoadUrlUsageLocation.extend(res)
def findKeystoreUsage(self): grep = Grep( "invoke-virtual {(.*)}, Ljava\/security\/KeyStore;->getEntry\(Ljava\/lang\/String;Ljava\/security\/KeyStore\$ProtectionParameter;\)Ljava\/security\/KeyStore\$Entry", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) self.keystoreLocations.extend(res)
def findDynamicRegisteredBroadcastReceivers(self): grep = Grep( ";->registerReceiver\(Landroid\/content\/BroadcastReceiver;Landroid\/content\/IntentFilter;\)", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) self.dynamicRegisteredBroadcastReceiversLocations.extend(res)
def findPathTraversalContentProvider(self): grep = Grep("\.super Landroid\/content\/ContentProvider;", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: instructions = self.getFileContent(location) indexList = self.findInstructionIndex(instructions, "") if len(indexList) > 0: indexList = self.findInstructionIndex(instructions, "")
def checkCustomPinningImplementation(self): grep = Grep( "invoke-virtual {(.*)}, Ljavax\/net\/ssl\/TrustManagerFactory;->init\(Ljava\/security\/KeyStore;\)V", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: if "/okhttp" in location or "io/fabric" in location: continue self.customCertifificatePinningLocation.append(location)
def checkVulnerableSockets(self): grep = Grep( "Ljavax\/net\/SocketFactory;->createSocket\(Ljava\/lang\/String;I\)Ljava\/net\/Socket;", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: instructions = self.getFileContent(location) indexList = self.findInstructionIndex( instructions, "Ljavax/net/ssl/HostnameVerifier;->verify\(Ljava/lang/String;Ljavax/net/ssl/SSLSession;\)Z" ) if indexList: self.vulnerableSocketsLocations.append(location)
def checkInsecureHostnameVerifier(self): # .implements Ljavax/net/ssl/HostnameVerifier; grep = Grep("\.implements Ljavax\/net\/ssl\/HostnameVerifier;", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: method = self.getMethod( r"\.method .* verify\(Ljava\/lang\/String;Ljavax\/net\/ssl\/SSLSession;\)Z", r"\.end method", location) if not method: continue if self.doesMethodReturnTrue(method) is True: self.vulnerableHostnameVerifiers.append(location)
def findPropertyEnabledWebViews(self): grep = Grep(";->getSettings\(\)Landroid\/webkit\/WebSettings;", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: instructions = self.getFileContent(location) indexList = self.findInstructionIndex( instructions, "Landroid/webkit/WebSettings;->setJavaScriptEnabled\(Z\)V") if len(indexList) > 0: for index in indexList: register = self.findRegistersPassedToFunction( instructions[index]) value = self.findRegisterAssignedValueFromIndexBackwards( instructions, register[1], index) if value == "0x1": self.javascriptEnabledWebviews.append(location) indexList = self.findInstructionIndex( instructions, "Landroid/webkit/WebSettings;->setAllowFileAccess\(Z\)V") if len(indexList) > 0: for index in indexList: register = self.findRegistersPassedToFunction( instructions[index]) value = self.findRegisterAssignedValueFromIndexBackwards( instructions, register[1], index) if value == "0x1": self.fileAccessEnabledWebviews.append(location) else: self.fileAccessEnabledWebviews.append(location) indexList = self.findInstructionIndex( instructions, "Landroid/webkit/WebSettings;->setAllowUniversalAccessFromFileURLs\(Z\)V" ) if len(indexList) > 0: for index in indexList: register = self.findRegistersPassedToFunction( instructions[index]) value = self.findRegisterAssignedValueFromIndexBackwards( instructions, register[1], index) if value == "0x1": self.universalAccessFromFileURLEnabledWebviewsLocations.append( location)
def checkOKHttpCertificatePinning(self): grep = Grep( "add\(Ljava\/lang\/String;\[Ljava\/lang\/String;\)Lokhttp3\/CertificatePinner\$Builder", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: # Bypass library files if "/okhttp" in location: continue instructions = self.getFileContent(location) indexList = self.findInstructionIndex( instructions, "certificatePinner\(Lokhttp3/CertificatePinner;\)Lokhttp3/OkHttpClient$Builder;" ) if indexList: self.okHttpCertificatePinningLocation.append(location)
def findWebviewJavascriptInterfaceUsage(self): grep = Grep( ";->addJavascriptInterface\(Ljava\/lang\/Object;Ljava\/lang\/String;\)V", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: instructions = self.getFileContent(location) indexList = self.findInstructionIndex( instructions, ";->addJavascriptInterface\(Ljava/lang/Object;Ljava/lang/String;\)V" ) if len(indexList) != 0: for index in indexList: registers = self.findRegistersPassedToFunction( instructions[index]) self.webViewAddJavascriptInterfaceUsageLocation.append( location)
def checkVulnerableHostnameVerifiers(self): grep = Grep( "invoke-virtual {(.*)}, Lorg\/apache\/http\/conn\/ssl\/SSLSocketFactory;->setHostnameVerifier\(Lorg\/apache\/http\/conn\/ssl\/X509HostnameVerifier;\)V", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: instructions = self.getFileContent(location) indexList = self.findInstructionIndex( instructions, "Lorg/apache/http/conn/ssl/SSLSocketFactory;->setHostnameVerifier" ) for index in indexList: registers = self.findRegistersPassedToFunction( instructions[index]) if self.findRegisterAssignedValueFromIndexBackwards( instructions, registers[1], index ) == "Lorg/apache/http/conn/ssl/SSLSocketFactory;->ALLOW_ALL_HOSTNAME_VERIFIER:Lorg/apache/http/conn/ssl/X509HostnameVerifier;": self.vulnerableSetHostnameVerifiers.append(location)
def doesActivityHasFlagSecure(self, activity): if activity.startswith("."): activityName = self.apk.apk.get_package() + activity else: activityName = activity activityName = activityName.replace("$", "\$").replace(".", "/") grep = Grep("\.class public([a-zA-Z\s]*)L" + activityName + ";", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) if not res: log.warning("Could not find file for activity: %s", activity) for file_path in res: self.activityLocations[activity] = file_path method = self.getMethod( r"\.method ([a-zA-Z]*) onCreate\(Landroid\/os\/Bundle;\)V", r"\.end method", file_path) register = self.findRegisterByAssignedValue(method, "0x2000") if not register: return False # invoke-virtual {p1, v0, v0}, Landroid/view/Window;->setFlags(II)V grep = Grep( "invoke-virtual(.*)" + register + "(.*)Landroid\/view\/Window;->setFlags\(II\)V", self.dir_exclusions, self.file_exclusions) return grep.check_file(file_path)
def checkVulnerableTrustManagers(self): grep = Grep( "\.method public checkClientTrusted\(\[Ljava\/security\/cert\/X509Certificate;Ljava\/lang\/String;\)V", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: method = self.getMethod(r"\.method public checkClientTrusted\(", r"\.end method", location) if not method: continue if not self.isMethodEmpty(method): continue grep = Grep( "\.method public getAcceptedIssuers\(\)\[Ljava\/security\/cert\/X509Certificate;", self.dir_exclusions, self.file_exclusions) if grep.check_file(location): method = self.getMethod( r"\.method public getAcceptedIssuers\(\)\[Ljava\/security\/cert\/X509Certificate;", r"\.end method", location) if not method: continue # new-array v0, v0, [Ljava/security/cert/X509Certificate; if not self.doesMethodReturnNull( method, "new-array v0, v0, [Ljava/security/cert/X509Certificate;" ): continue grep = Grep( "\.method public checkServerTrusted\(\[Ljava\/security\/cert\/X509Certificate;Ljava\/lang\/String;\)V", self.dir_exclusions, self.file_exclusions) if grep.check_file(location): method = self.getMethod( r"\.method public checkServerTrusted\(", r"\.end method", location) if self.isMethodEmpty(method): self.vulnerableTrustManagers.append(location)
def findWeakCryptographicUsage(self): grep = Grep( "Ljavax\/crypto\/Cipher;->getInstance\(Ljava\/lang\/String;\)Ljavax\/crypto\/Cipher;", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) for location in res: instructions = self.getFileContent(location) indexList = self.findInstructionIndex( instructions, "Ljavax/crypto/Cipher;->getInstance\(Ljava/lang/String;\)Ljavax/crypto/Cipher;" ) for index in indexList: register = self.findRegistersPassedToFunction( instructions[index]) transformationValue = self.findRegisterAssignedValueFromIndexBackwards( instructions, register[0], index) if transformationValue is not None: if transformationValue == "\"AES\"" or "AES/ECB/" in transformationValue: self.AESwithECBLocations.append(location) elif "DES" in transformationValue: self.DESLocations.append(location)
def doesPreferenceActivityHasValidFragmentCheck(self, activity): if activity.startswith("."): activityName = self.apk.apk.get_package() + activity else: activityName = activity activityName = activityName.replace("$", "\$").replace(".", "/") # Check if activity location was previously found if activity in self.activityLocations: res = [self.activityLocations[activity]] else: grep = Grep("\.class public([a-zA-Z\s]*)L" + activity + ";", self.dir_exclusions, self.file_exclusions) res = grep.check_directories(self.smaliPaths) if not res: log.warning("Could not find file for activity: %s", activity) for file_path in res: self.activityLocations[activity] = file_path grep = Grep("\.super Landroid\/preference\/PreferenceActivity;", self.dir_exclusions, self.file_exclusions) if grep.check_file(file_path): log.warning("Activity extends PreferenceActivity: %s", file_path) method = self.getMethod( r"\.method protected isValidFragment\(Ljava\/lang\/String;\)Z", r"\.end method", file_path) log.warning("isValidFragment() method: %s", "\n".join(method)) if method: return True else: return False return None