精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Android漏洞掃描工具Code Arbiter

企業動態
目前Android應用代碼漏洞掃描工具種類繁多,效果良莠不齊,這些工具有一個共同的特點,都是在應用打包完成后對應用進行解包掃描。這種掃描有非常明顯的缺點,掃描周期較長,不能向開發者實時反饋代碼中存在的安全問題,并且對于問題代碼的定位需要手動搜索匹配源碼,這樣就更不利于開發者對問題代碼進行及時的修改。

[[201139]]

目前Android應用代碼漏洞掃描工具種類繁多,效果良莠不齊,這些工具有一個共同的特點,都是在應用打包完成后對應用進行解包掃描。這種掃描有非常明顯的缺點,掃描周期較長,不能向開發者實時反饋代碼中存在的安全問題,并且對于問題代碼的定位需要手動搜索匹配源碼,這樣就更不利于開發者對問題代碼進行及時的修改。Code Arbiter正是為解決上述兩個問題而開發的,專門對Android Studio中的源碼進行安全掃描。

1 背景介紹

為實現對Android Studio中的源碼進行掃描,最方便的方式便是將掃描工具以IDE插件的形式進行工作。此時一個很自然的想法便是從頭構建一個Android Studio插件,但是進行仔細的評估后會發現,這樣做難度并不?。?/p>

工作量大,許多知識需要學習,如IDE開放API接口、插件UI構建等,同時許多底層模塊需要從頭構建;

插件的穩定性、檢測問題的準確性上都不一定能夠達到已有開源工具的效果。

因此我們轉而考慮在已有漏洞檢測插件的基礎上進行擴展,以滿足需求。經過調研,最終入圍的兩款檢測插件是PMD和FindBugs,其中PMD是對Java源碼進行掃描,而FindBugs則是對Java源碼編譯后的class文件進行掃描??紤]到可擴展性及檢測的準確性,最終選定了FindBugs。FindBugs是一個靜態分析工具,它檢查類或者JAR文件,將字節碼與一組缺陷模式進行對比來發現可能的問題,可以以獨立的JAR包形式運行,也可以作為集成開發工具的插件形式存在。

擴展優化

那么,怎么擴展FindBugs呢?調研發現FindBugs插件具有著極強的可擴展性,只需要將擴展的JAR包導入FindBugs插件,重啟,即可完成相關功能的擴展。安裝JAR包示意圖如下所示。

 

下面的問題是如何構建可安裝的JAR包。繼續調研,發現FindBugs有一款專門對安全問題進行檢測的擴展插件Find Security Bugs,該插件主要用于對Web安全問題進行檢測,也有極少對Android相關安全問題的檢測規則。考慮以下幾個原因,需要對該插件的源碼進行重構。

對Android安全問題的檢測太少,只包含外部文件使用、Webview、Broadcast使用等寥寥幾項;

檢測的細粒度上考慮不夠完全,會造成大量的誤報,無法滿足檢測精度的要求;

檢測問題的上報只支持英文模式,且問題展示的邏輯性不夠嚴謹,不便于開發者進行問題排查。

基于以上三個原因,我們需要對Find Security Bugs的源碼進行重寫、優化,通過增加檢測項來檢測盡可能多的安全問題,通過優化檢測規則來減少檢測的誤報,問題展示使用中文進行描述,同時優化問題描述的邏輯性,使得開發者能夠更易理解并修改相關問題,至此插件實現及優化的方案確定。

2 工具實現介紹

FindBugs檢測的是class文件,因此當待檢測的源碼未生成編譯文件時,FindBugs會先將源碼編譯生成.class文件,然后對這個class文件進行分析。FindBugs會完成對class文件的自動建模,在此模型的基礎上對代碼進行分析。按照在實際編寫檢測代碼過程中的總結,把檢測的實現方式分成四種方式,下面分別進行介紹。

2.1 逐行檢查

逐行檢查主要是針對代碼中使用的一些不安全方法或參數進行檢測,其實現方式是重寫sawOpcode()方法,下面以Android中使用外部存儲問題作為示例進行講解。

Android中獲取外部存儲文件夾地址的方法主要包括下面這些方法:

  1. getExternalCacheDir() 
  2. getExternalCacheDirs() 
  3. getExternalFilesDir() 
  4. getExternalFilesDirs() 
  5. getExternalMediaDirs() 
  6. Environment.getExternalStorageDirectory() 
  7. Environment.getExternalStoragePublicDirectory() 

檢測的方式便是,如果發現存在該方法的調用,則作為一個問題進行上報,實現完整代碼如下所示:

  1. public class ExternalFileAccessDetector extends OpcodeStackDetector { 
  2.  
  3.     private static final String ANDROID_EXTERNAL_FILE_ACCESS_TYPE = "ANDROID_EXTERNAL_FILE_ACCESS"
  4.     private BugReporter bugReporter; 
  5.     public ExternalFileAccessDetector(BugReporter bugReporter) { 
  6.         this.bugReporter = bugReporter; 
  7.     } 
  8.  
  9.     @Override 
  10.  public void sawOpcode(int seen) { 
  11.         //printOpCode(seen); 
  12.  if (seen == Constants.INVOKEVIRTUAL && ( 
  13.         getNameConstantOperand().equals("getExternalCacheDir") || 
  14.         getNameConstantOperand().equals("getExternalCacheDirs") || 
  15.         getNameConstantOperand().equals("getExternalFilesDir") || 
  16.         getNameConstantOperand().equals("getExternalFilesDirs") || 
  17.         getNameConstantOperand().equals("getExternalMediaDirs"
  18.             )) { 
  19. // System.out.println(getSigConstantOperand()); 
  20.  bugReporter.reportBug(new BugInstance(this, ANDROID_EXTERNAL_FILE_ACCESS_TYPE, Priorities.NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this)); 
  21.         } 
  22.         else if(seen == Constants.INVOKESTATIC && getClassConstantOperand().equals("android/os/Environment") && (getNameConstantOperand().equals("getExternalStorageDirectory") || getNameConstantOperand().equals("getExternalStoragePublicDirectory"))) { 
  23.             bugReporter.reportBug(new BugInstance(this, ANDROID_EXTERNAL_FILE_ACCESS_TYPE, Priorities.NORMAL_PRIORITY).addClass(this).addMethod(this).addSourceLine(this)); 
  24.         } 
  25.     } 

該類的實現是繼承OpcodeStackDetector類,是FindBugs中的一個抽象類,封裝了對于獲取代碼特定參數的方法調用。sawOpcode方法參數可以理解為待檢測代碼行的行號,通過printOpCode(seen)可以打印該代碼行的具體內容。Constants.INVOKEVIRTUAL表示該行調用類的實例方法,Constants.INVOKESTATIC表示調用類的靜態方法。getNameConstantOperand方法表示獲取被調用方法的名稱,getClassConstantOperand方法表示獲取調用類的名稱,getSigConstantOperand方法表示獲取方法的所有參數。bugReporter.reportBug用于上報檢測到的漏洞信息,其中BugInstance的三個參數分別表示:檢測器、漏洞類型、漏洞等級,其中漏洞等級分為五個級別,如下表所示:

addClass、addMethod、addSourceLine用于指定該漏洞所在的類、方法、行,方便報告漏洞時定位關鍵代碼。

2.2 逐方法檢查

逐方法檢查首先獲取待檢測類的所有內容,然后對類中的方法進行逐個檢查,多用于對方法體進行檢測,其實現的方法主要是通過重寫visitClassContext方法,下面以對Android TrustManager的空實現的檢測為例進行說明。

TrustManager的空實現,主要是指對于檢測Server端證書是否可信的方法checkServerTrusted,是否是空實現。下面展示問題代碼,如果是空實現那么將導致客戶端接收任意證書,從而造成加密后的HTTPS消息被中間人解密。

  1. @Override 
  2. public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { 
  3.  

檢測的方式是通過遍歷類中的所有方法,找到checkServerTrusted方法,對方法整體進行檢測,確定其是否為空實現,部分代碼如下所示:

  1. public class WeakTrustManagerDetector implements Detector { 
  2. ... 
  3. public WeakTrustManagerDetector(BugReporter bugReporter) { 
  4.         this.bugReporter = bugReporter; 
  5.     } 
  6.  
  7.     @Override 
  8.  public void visitClassContext(ClassContext classContext) { 
  9.         JavaClass javaClass = classContext.getJavaClass(); 
  10.  
  11.         //The class extends X509TrustManager 
  12.   boolean isTrustManager = InterfaceUtils.isSubtype(javaClass,"javax.net.ssl.X509TrustManager"); 
  13.         boolean isHostnameVerifier = InterfaceUtils.isSubtype(javaClass,"javax.net.ssl.HostnameVerifier"); 
  14.  
  15. // if (!isTrustManager && !isHostnameVerifier) return
  16.  if (!isTrustManager && !isHostnameVerifier){ 
  17.             for (Method m : javaClass.getMethods()) { 
  18.                 allow_All_Hostname_Verify(classContext, javaClass, m); 
  19.             } 
  20.         } 
  21.  
  22.         Method[] methodList = javaClass.getMethods(); 
  23.  
  24.         for (Method m : methodList) { 
  25.             MethodGen methodGen = classContext.getMethodGen(m); 
  26.  
  27.             if (DEBUG) System.out.println(">>> Method: " + m.getName()); 
  28.  
  29.             if (isTrustManager && 
  30.                     (m.getName().equals("checkClientTrusted") || 
  31.                      m.getName().equals("checkServerTrusted") || 
  32.                      m.getName().equals("getAcceptedIssuers"))) { 
  33.                 if(isEmptyImplementation(methodGen)) { 
  34.                     bugReporter.reportBug(new BugInstance(this, WEAK_TRUST_MANAGER_TYPE, Priorities.NORMAL_PRIORITY).addClassAndMethod(javaClass, m)); 
  35.                 } 
  36. ...... 

classContext.getJavaClass用于獲取整個類的所有內容;javaClass.getMethods用于獲取該類中的所有方法,以一個方法列表的形式返回;classContext.getMethodGen用于獲取該方法的內容;isEmptyImplementation將方法的內容導入該函數進行檢測,用于確定方法是否是空實現,該方法的代碼如下所示:

  1. private boolean isEmptyImplementation(MethodGen methodGen){ 
  2.     boolean invokeInst = false
  3.     boolean loadField = false
  4.  
  5.     for (Iterator itIns = methodGen.getInstructionList().iterator();itIns.hasNext();) { 
  6.         Instruction inst = ((InstructionHandle) itIns.next()).getInstruction(); 
  7.         if (DEBUG) 
  8.             System.out.println(inst.toString(true)); 
  9.  
  10.         if (inst instanceof InvokeInstruction) { 
  11.             invokeInst = true
  12.         } 
  13.         if (inst instanceof GETFIELD) { 
  14.             loadField = true
  15.         } 
  16.     } 
  17.     return !invokeInst && !loadField; 

該方法主要用于檢測方法中是否包含方法調用、域操作,如果沒有包含則認為是一個空實現的方法。因此該方法對于只包含 return true/false 語句的方法體同樣認為是一個空實現。

2.3 污點分析

數據流分析主要用于分析特定方法加載的參數是否能夠被用戶控制,即進行污點分析。做污點分析首先需要定義污染源(source點),污染源可以理解為能夠被用戶控制的輸入數據,這里定義的Android污染源主要包括用戶的輸入、Intent傳入的數據,下面展示定義的部分污染源(source點):

  1. - EditText 
  2. android/widget/EditText.getText()Landroid/text/Editable;:TAINTED 
  3. - Intent 
  4. android/content/Intent.getAction()Ljava/lang/String;:TAINTED 
  5. android/content/Intent.getStringExtra(Ljava/lang/String;)Ljava/lang/String;:TAINTED 
  6. ...... 
  7. - Bundle 
  8. android/os/Bundle.get(Ljava/lang/String;)Ljava/lang/Object;:TAINTED 
  9. android/os/Bundle.getString(Ljava/lang/String;)Ljava/lang/String;:TAINTED 
  10. ...... 

定義好污染源后就需要確定污染的觸發點(sink點),可以理解為會觸發危險操作的函數。定義sink點的方式有兩種,一種是直接從文件中導入,以命令注入為示例,代碼如下:

  1. public class CommandInjectionDetector extends BasicInjectionDetector { 
  2.  
  3.     public CommandInjectionDetector(BugReporter bugReporter) { 
  4.         super(bugReporter); 
  5.         loadConfiguredSinks("command.txt""COMMAND_INJECTION"); 
  6.  } 

從代碼中可以清楚的看到其導入方式是繼承BasicInjectionDetector類,然后再該類的構造方法中通過loadConfiguredSinks方法,導入包含sink點的文件,下面展示該示例文件中的內容:

  1. java/lang/Runtime.exec(Ljava/lang/String;)Ljava/lang/Process;:0 
  2. java/lang/Runtime.exec([Ljava/lang/String;)Ljava/lang/Process;:0 
  3. java/lang/Runtime.exec(Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Process;:0,1 
  4. java/lang/Runtime.exec([Ljava/lang/String;[Ljava/lang/String;)Ljava/lang/Process;:0,1 
  5. java/lang/Runtime.exec(Ljava/lang/String;[Ljava/lang/String;Ljava/io/File;)Ljava/lang/Process;:1,2 
  6. java/lang/Runtime.exec([Ljava/lang/String;[Ljava/lang/String;Ljava/io/File;)Ljava/lang/Process;:1,2 
  7. java/lang/ProcessBuilder.<init>([Ljava/lang/String;)V:0 
  8. java/lang/ProcessBuilder.<init>(Ljava/util/List;)V:0 
  9. java/lang/ProcessBuilder.command([Ljava/lang/String;)Ljava/lang/ProcessBuilder;:0 
  10. java/lang/ProcessBuilder.command(Ljava/util/List;)Ljava/lang/ProcessBuilder;:0 
  11. dalvik/system/DexClassLoader.loadClass(Ljava/lang/String;)Ljava/lang/Class;:0 

另一種是自定義導入,其實現是通過覆蓋BasicInjectionDetector類中的getInjectionPoint方法,以WebView.loadurl方法為例,示例代碼如下所示:

  1. @Override 
  2.  protected InjectionPoint getInjectionPoint(InvokeInstruction invoke, ConstantPoolGen cpg, InstructionHandle handle) { 
  3.         assert invoke != null && cpg != null
  4.         String method = invoke.getMethodName(cpg); 
  5.         String sig    = invoke.getSignature(cpg); 
  6. // System.out.println(invoke.getClassName(cpg)); 
  7.  if(sig.contains("Ljava/lang/String;")) { 
  8.             if("loadUrl".equals(method)){ 
  9.                 if(sig.contains("Ljava/util/Map;")){ 
  10.                     return new InjectionPoint(new int[]{1}, WEBVIEW_LOAD_DATA_URL_TYPE); 
  11.                 }else
  12.                     return new InjectionPoint(new int[]{0}, WEBVIEW_LOAD_DATA_URL_TYPE); 
  13.                 } 
  14.             }else if("loadData".equals(method)){ 
  15.                 return new InjectionPoint(new int[]{2}, WEBVIEW_LOAD_DATA_URL_TYPE); 
  16.             }else if("loadDataWithBaseURL".equals(method)){ 
  17.                 //BUG 
  18.  return new InjectionPoint(new int[]{4}, WEBVIEW_LOAD_DATA_URL_TYPE); 
  19.             } 
  20.         } 
  21.         return InjectionPoint.NONE; 
  22.     } 

通過實例化InjectionPoint類構造新的sink點,其構造方法中的第一個參數表示該方法接收污染數據參數的位置,如方法為webView.loadUrl(url),其第一個參數就是new int[]{0},其它的以此類推。

上報發現漏洞的情況,則通過覆蓋getPriorityFromTaintFrame方法的實現,示例代碼如下所示:

  1. @Override 
  2.  protected int getPriorityFromTaintFrame(TaintFrame fact, int offset) 
  3.             throws DataflowAnalysisException { 
  4.         Taint stringValue = fact.getStackValue(offset); 
  5. // System.out.println(stringValue.getConstantValue()); 
  6.  if (stringValue.isTainted() || stringValue.isUnknown()) { 
  7.             return Priorities.NORMAL_PRIORITY; 
  8.         } else { 
  9.             return Priorities.IGNORE_PRIORITY; 
  10.         } 
  11.     } 

通過fact.getStackValue獲取檢測的函數變量,如果該變量被污染(isTainted)或 變量是否被污染未知(但是是可控制變量),那么作為一個中危風險(Priorities.NORMAL_PRIORITY)進行上報,其它的情況則上報為可忽略風險(Priorities.IGNORE_PRIORITY)。

2.4 自定義代碼檢測

自定義代碼檢測實現的前半部分同2.2的逐方法檢測類似,均是獲取類的內容,然后遍歷所有的方法,對方法的內容進行檢測,但是在具體代碼檢測實現上是通過自定義分析進行。目前自定義檢測只應用到Android中本地拒絕服務的檢測。本地拒絕服務的被觸發的重要原因在于對通過Intent獲取的參數未進行異常捕獲,因此檢測實現的方式便是檢測獲取參數的代碼行是否被try catch包裹(這個存在誤差,待改進)。對于其代碼分析,不能使用FindBugs模型進行分析,而是使用最原始的class代碼進行分析,原始class代碼的形式通過javap命令進行查看,下圖展示示例代碼。

 

對原始class文件進行分析存在的缺陷是無法定位具體的代碼行,那么在進行問題上報時無法將問題定位到代碼行,因此第一步需要在原有模型的基礎上對所有包含Intent獲取參數的方法的位置存儲到一個Map結構中,方便后面對方法的定位,代碼實現如下所示,獲取方法所在的行,然后以方法名作為Key值,以代碼行相關信息作為Value值,存儲到Map中。

  1. private Map<String, List<Location>> get_line_location(Method m, ClassContext classContext){ 
  2.         HashMap<String, List<Location>> all_line_location = new HashMap<>(); 
  3.         ConstantPoolGen cpg = classContext.getConstantPoolGen(); 
  4.         CFG cfg = null
  5.         try { 
  6.             cfg = classContext.getCFG(m); 
  7.         } catch (CFGBuilderException e) { 
  8.             e.printStackTrace(); 
  9.             return all_line_location; 
  10.         } 
  11.         for (Iterator<Location> i = cfg.locationIterator(); i.hasNext(); ) { 
  12.             Location loc = i.next(); 
  13.             Instruction inst = loc.getHandle().getInstruction(); 
  14.             if(inst instanceof INVOKEVIRTUAL) { 
  15.                 INVOKEVIRTUAL invoke = (INVOKEVIRTUAL) inst; 
  16.  if(all_line_location.containsKey(invoke.getMethodName(cpg))){ 
  17.                         all_line_location.get(invoke.getMethodName(cpg)).add(loc); 
  18.                     }else { 
  19.                         LinkedList<Location> loc_list = new LinkedList<>(); 
  20.                         loc_list.add(loc); 
  21.                         all_line_location.put(invoke.getMethodName(cpg), loc_list); 
  22.                     } 
  23. // } 
  24.  } 
  25.         } 
  26.         return all_line_location; 
  27.     } 

之后獲取Exception包裹的范圍,FindBugs中包含對Exception的建模,因此能夠通過其模型能夠直接獲取其范圍并存儲到一個列表中,代碼如下所示,其中exceptionTable[i].getStartPC用于獲取try catch 的起始代碼行,exceptionTable[i].getEndPC用于獲取try catch 的結束代碼行。

  1. public int[] getExceptionScope(){ 
  2.         try { 
  3.             CodeException[] exceptionTable = this.code.getExceptionTable(); 
  4.             int[] exception_scop = new int[exceptionTable.length * 2]; 
  5.             for (int i = 0; i < exceptionTable.length; i++) { 
  6.                 exception_scop[i * 2] = exceptionTable[i].getStartPC(); 
  7.                 exception_scop[i * 2 + 1] = exceptionTable[i].getEndPC(); 
  8.             } 
  9.             return exception_scop; 
  10.         }catch (Exception e){ 
  11.  } 
  12.         return new int[0]; 
  13.     } 

在對代碼進行逐行檢查時,因為使用的是最原始class文件形式,因此需要限定其遍歷的范圍,限定的方式是通過代碼的行號,即上圖中每行代碼的第一個數值。首先需要獲取代碼總行數的大小,獲取的方式便是解析FindBugs建模后的第一行代碼,找到關鍵詞code-length后面的數值,即為代碼的行數,解析代碼如下所示:

  1. public int get_Code_Length(String firstLineCode){ 
  2.         try{ 
  3.             String[] split1 = firstLineCode.split("code_length"); 
  4. // System.out.println(split1[split1.length-1]); 
  5.  byte[] code_length_bytes = split1[split1.length-1].getBytes(); 
  6.             byte[] new_code_bytes = new byte[code_length_bytes.length]; 
  7.             for(int i=0; i<code_length_bytes.length; i++){ 
  8. // System.out.println(); 
  9.  if(code_length_bytes[i]<48 || code_length_bytes[i]>57){ 
  10.                     new_code_bytes[i] = 32; 
  11.                 }else
  12.                     new_code_bytes[i] = code_length_bytes[i]; 
  13.                 } 
  14.             } 
  15.             return Integer.parseInt(new String(new_code_bytes).trim()); 
  16.         }catch(Exception e){ 
  17.             e.printStackTrace(); 
  18.         } 
  19.         return 0; 
  20.     } 

最后對代碼進行逐行遍歷,遍歷中為防止try catch塊被遍歷到,使用行號來限制遍歷的范圍。檢測代碼行是否包含通過Intent獲取參數,及該行是否被try catch 包裹,如果上述兩個條件均被觸發,那么就作為一個問題進行上報。示例代碼如下,其中get_code_line_index方法用于獲取代碼的行號,獲取的方式是截取代碼行的首字符的數值,以確定是否在代碼包裹的范圍內。

  1. private void analyzeMethod(JavaClass javaClass, Method m, ClassContext classContext) throws CFGBuilderException { 
  2.         HashMap<String, List<Location>> all_line_location = (HashMap<String, List<Location>>) get_line_location(m, classContext); 
  3.         Code code = m.getCode(); 
  4.         StringCodeAnalysis sca = new StringCodeAnalysis(code); 
  5.         String[] codes = sca.codes_String_Array(); 
  6.         int code_length = sca.get_Code_Length(sca.get_First_Code(codes)); 
  7.         int[] exception_scop = sca.getExceptionScope(); 
  8.         for(int i=1; i<codes.length; i++){ 
  9.             int line_index = sca.get_code_line_index(codes[i]); 
  10.             if (line_index < code_length){ 
  11.                 if(codes[i].toLowerCase().contains("invokevirtual") && 
  12.                         (codes[i].contains("android.content.Intent.get")  || codes[i].contains("android.os.Bundle.get"))){ 
  13.                     if(exception_scop.length == 0){ 
  14.                         ...... 
  15.                     }else
  16.                         boolean is_scope = false
  17.                         for(int j=0; j<exception_scop.length; j+=2){ 
  18.                             int start = exception_scop[j]; 
  19.                             int end = exception_scop[j+1]; 
  20.                             if(line_index >= start && line_index <= end){ 
  21.                                 is_scope = true
  22.                             } 
  23.                             if(is_scope){ 
  24.                                 break; 
  25.                             } 
  26.                         } 
  27.                         if(!is_scope){ 
  28.                             String method_name = get_method_name(codes[i]); 
  29.                             if(all_line_location.containsKey(method_name)){ 
  30.                                 for(Location loc : all_line_location.get(method_name)){ 
  31.                                     bugReporter.reportBug(new BugInstance(this, LOCAL_DENIAL_SERVICE_TYPE, Priorities.NORMAL_PRIORITY).addClass(javaClass).addMethod(javaClass, m).addSourceLine(classContext, m, loc)); 
  32.                                 } 
  33.                             }else { 
  34.                                 bugReporter.reportBug(new BugInstance(this, LOCAL_DENIAL_SERVICE_TYPE, Priorities.NORMAL_PRIORITY).addClass(javaClass).addMethod(javaClass, m)); 
  35.  } 
  36.                         } 
  37.                     } 
  38.                 } 
  39.             } 
  40.         } 
  41.     } 

3 注冊打包

上面詳細敘述了如何構造自己的問題檢測代碼,完成檢測方法的書寫后,下一步就是在配置文件中對檢測方法進行注冊,才能使檢測代碼運轉起來。

需要在兩個文件中進行注冊,第一個是findbugs.xml,注冊示例如下:

  1. <Detector class="com.h3xstream.findsecbugs.android.LocalDenialOfServiceDetector" reports="LOCAL_DENIAL_SERVICE"/> 
  2. <BugPattern type="LOCAL_DENIAL_SERVICE" abbrev="SECLDOS" category="Android安全問題" cweid="276"/> 

其中Detector用于注冊該檢測方法的位置及其唯一標識,BugPattern用于對檢測出的問題進行歸類,方便展示,如此處歸類到"Android安全問題"中,那么在生成報告的時候問題也將被歸類到"Android安全問題"中。

第二個是messages.xml注冊,注冊示例如下,該注冊主要是對該問題進行說明,包括問題的危害及修復方法。

  1. <Detector class="com.h3xstream.findsecbugs.android.LocalDenialOfServiceDetector">
<Details>Local Denial of Service.</Details>
</Detector>
<BugPattern type="LOCAL_DENIAL_SERVICE">
<ShortDescription>本地拒絕服務</ShortDescription>
<LongDescription>通過Intent接收的參數未進行異常捕獲,導致出現異常使得應用崩潰</LongDescription>
<Details>
<![CDATA[
    <p>
        <b>危害:</b><br/>
        <pre>
            應用崩潰無法使用,影響用戶體驗;
            被競爭對手利用,進行點對點攻擊。
        </pre>
    </p>
    <p>
        <b>錯誤代碼:</b><br/>
        <pre>
            bundle.getString(""); //未try/catch
            intent.getStringExtra(""); //未try/catch
        </pre>
    </p>
    <p>
        <b>解決方案:</b><br/>
        <pre>
            對通過Intent接收的參數處理時,進行嚴格的異常捕獲。
            try {
                bundle.getString("");
                intent.getStringExtra(""); 
            }catch (Exception e){}
        </pre>
    </p>
]]>
</Details>
</BugPattern>
<BugCode abbrev="SECLDOS">本地拒絕服務</BugCode> 

一切完成就緒后使用Maven進行打包,就生產了供FindBugs集成開發工具插件使用的JAR包,完成安裝并重啟,即可使用自定義插件對特定問題進行檢測。

最終分析的效果圖如下圖所示:

 

4 結語

本文介紹了Android集成開發環境Android Studio的代碼實時檢測工具Code Arbiter的產生原因及代碼實現,最后展示了分析的效果。通過Code Arbiter在生產環境中的應用,其檢測效果還是相當不錯,能夠發現很多編碼過程中存在的問題。但是Code Arbiter仍然存在許多不足,需要優化。后續將在以下兩個方面對工具進行改進:

擴大漏洞檢測范圍,使Code Arbiter能夠囊括Android編碼常見安全問題;

優化漏洞檢測規則,提高檢測的準確性,減少誤報。

5 作者簡介

建弋,2016年加入美團點評,目前主要負責金融部門相關的安全工作。

【本文為51CTO專欄機構“美團點評技術團隊”的原創稿件,轉載請通過微信公眾號聯系機構獲取授權】

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 51CTO專欄
相關推薦

2017-05-12 14:25:09

2013-05-20 11:54:55

2010-09-17 16:16:28

2014-01-16 16:34:22

2010-12-01 11:36:44

2011-03-15 14:19:50

2014-12-08 09:01:53

2010-09-25 10:25:23

2020-08-04 22:21:54

漏洞掃描工具惡意軟件

2010-09-25 10:34:20

2010-09-26 13:25:16

2024-01-18 09:00:00

漏洞Docker工具

2021-09-30 09:00:00

漏洞安全工具

2018-09-10 11:07:19

2022-07-10 00:01:43

漏洞工具安全

2024-01-18 16:11:21

2020-07-13 07:18:26

滲透測試漏洞掃描工具

2019-11-08 09:12:35

Linux掃描儀軟件

2025-03-19 13:02:57

2023-08-21 00:12:23

點贊
收藏

51CTO技術棧公眾號

国产91xxx| 亚洲综合在线做性| 免费一级黄色录像| 日本成人精品| 婷婷夜色潮精品综合在线| 麻豆成人av| 国产精品无码专区av免费播放| 欧美精品一卡| 亚洲性av网站| 一级全黄裸体片| 欧美日韩五码| 亚洲福利视频一区二区| 日本欧洲国产一区二区| 99久久免费国产精精品| 一本久道久久综合狠狠爱| 永久免费毛片在线播放不卡| 亚洲精品无码久久久久久久| 欧美二三四区| 亚洲国产精品久久一线不卡| 日韩一区二区三区资源| 日韩在线视频第一页| 毛片一区二区三区| 77777亚洲午夜久久多人| 二区三区四区视频| 亚洲日产av中文字幕| 日韩一区二区影院| 少妇网站在线观看| 午夜激情在线播放| 亚洲一区二区综合| 在线视频欧美一区| 黄视频在线观看免费| 成人免费av网站| 亚洲一区二区三区久久| 波多野结衣黄色网址| 日韩天堂av| 欧美日韩福利视频| 五月综合色婷婷| 精品一区二区三| 日韩精品视频在线观看免费| 韩国黄色一级片| 色999韩欧美国产综合俺来也| 欧美日韩中文在线观看| 亚洲国产精品影视| www.av在线| 久久久蜜桃精品| 国外成人免费视频| 亚洲精品久久久久久动漫器材一区| 久久电影网站中文字幕| 国产91热爆ts人妖在线| 中文字幕亚洲精品在线| 国产精品v欧美精品v日本精品动漫| 中文亚洲视频在线| 亚洲做受高潮无遮挡| 日本欧美高清| 日韩经典中文字幕| 少妇精品一区二区三区| 人人精品视频| 亚洲免费精彩视频| 国产又粗又猛又爽又黄av | 国产精品99一区二区| 久久精品国产电影| 欧美成人aaa片一区国产精品| 久久精品久久久| 萌白酱国产一区二区| 久久久久久久久久久久久女过产乱| 久久久久国产| 欧美成人在线免费| 国产真实乱人偷精品视频| 激情欧美一区| 欧美亚洲另类视频| 成人av网站在线播放| 日产国产高清一区二区三区| 国产精品欧美日韩| 国产一区二区女内射| 国产乱人伦偷精品视频免下载| 成人女保姆的销魂服务| www.国产黄色| 91亚洲精品久久久蜜桃| 欧洲精品久久| 黄av在线播放| 午夜亚洲福利老司机| 欧美亚洲另类色图| 国产a亚洲精品| 日韩一区二区影院| jizz欧美性20| 99久久精品费精品国产风间由美| 欧美裸体xxxx极品少妇| 久久综合亚洲色hezyo国产| 亚洲免费一区二区| 国产日韩视频在线观看| www日本高清| 久久久久久久久99精品| 中文有码久久| 国内激情视频在线观看| 欧美在线视频全部完| 少妇献身老头系列| 国产亚洲精品美女久久久久久久久久| xxx欧美精品| 偷偷操不一样的久久| 麻豆精品视频在线观看免费 | 久久精品免费网站| 精品一区二区三区亚洲| 亚洲日本aⅴ片在线观看香蕉| 蜜桃视频最新网址| 国产亚洲网站| 亚洲xxxx3d| 黄色片免费在线| 亚洲综合丁香婷婷六月香| 蜜臀av午夜一区二区三区| 国产麻豆精品| 亚洲图片欧美日产| 久久无码精品丰满人妻| 免费成人你懂的| 精品国产乱码久久久久久88av| av免费观看一区二区| 五月综合激情日本mⅴ| 九色porny自拍| 网红女主播少妇精品视频| 两个人的视频www国产精品| 青青青国产在线| 成人黄页毛片网站| 影音先锋欧美在线| 免费在线观看一区| 日韩精品免费一线在线观看| 久久午夜无码鲁丝片午夜精品| 日韩av中文字幕一区二区三区| 国内精品二区| 在线观看免费视频你懂的| 欧美日本一区二区| 91社区视频在线观看| 乱码第一页成人| 国产伦精品一区二区三区照片91| 久久综合之合合综合久久| 一本久道久久综合中文字幕| 波多野结衣一二三区| 在线中文一区| 亚洲a中文字幕| 色综合久久久久综合一本到桃花网| 日韩欧美亚洲综合| 一级特级黄色片| 亚洲大胆在线| 国产精品我不卡| 黄页网站在线观看免费| 日韩视频免费观看高清完整版 | 欧美性生交xxxxx久久久| 亚洲一级av无码毛片精品| 国产精品观看| 国产精品久久波多野结衣| 欧美日韩经典丝袜| 欧美刺激午夜性久久久久久久| 秋霞欧美一区二区三区视频免费 | 午夜欧美2019年伦理 | 久久综合九色综合久久久精品综合| 波多野结衣 作品| 欧美日韩黄色| 欧美激情精品在线| 黄色一级大片在线免费看国产一 | 国产日本欧美一区二区| 波多野结衣家庭教师视频| 婷婷综合电影| 国产成人拍精品视频午夜网站| 国产女主播在线写真| 欧美亚一区二区| 天堂а√在线中文在线鲁大师| 理论片日本一区| 国产福利片一区二区| 国产精品亚洲欧美日韩一区在线| 欧美xxxx做受欧美| 黄色一级大片在线免费看国产一| 五月天久久比比资源色| 中文字幕丰满孑伦无码专区| 日韩av网站免费在线| 一区二区视频在线免费| 久久视频免费| 97国产一区二区精品久久呦| 日本福利片高清在线观看| 欧美亚洲综合在线| 国产精品丝袜一区二区| 成人激情视频网站| 能看的毛片网站| 91精品啪在线观看国产18| 国产99午夜精品一区二区三区| 日本不卡免费高清视频在线| 亚洲图片在区色| 国产农村老头老太视频| 婷婷国产在线综合| 日韩欧美黄色网址| 国产成人精品一区二| 成人久久久久久久久| 99久久.com| 免费日韩av电影| 婷婷激情成人| 91国内免费在线视频| h网站视频在线观看| 精品欧美一区二区三区精品久久 | 精品国产乱码久久久久久浪潮| 精品成人av一区二区在线播放| 欧美激情一区二区三区蜜桃视频| 韩国黄色一级片| 久久国产免费看| 蜜桃传媒一区二区三区| 999精品色在线播放| 精品无人乱码一区二区三区的优势| 久久久久久久性潮| 91av在线网站| 永久免费网站在线| 在线观看视频99| 亚洲欧美日韩精品永久在线| 337p亚洲精品色噜噜狠狠| 51国产偷自视频区视频| 一区二区三区在线观看视频| 五月天精品在线| 99久久久免费精品国产一区二区| 亚洲综合激情视频| 久久精品导航| 福利视频免费在线观看| 天天综合网91| 婷婷久久青草热一区二区| 另类在线视频| 都市激情久久久久久久久久久| 影音成人av| 日本精品在线视频| 狠狠躁少妇一区二区三区| 欧美乱妇高清无乱码| 黄色片免费在线观看| 在线精品国产欧美| 可以免费看污视频的网站在线| 精品电影一区二区| 国产国语亲子伦亲子| 欧美男人的天堂一二区| 成年人视频免费| 欧美性生交大片免网| 国产91色在线免费| 色资源在线观看| 亚洲黄色www网站| 亚洲av永久无码国产精品久久 | 欧美激情xxxxx| 国产视频中文字幕在线观看| 亚洲无限av看| 久久精品a一级国产免视看成人| 亚洲成人1234| 色哟哟国产精品色哟哟| 亚洲看片一区| 欧美成人黑人xx视频免费观看| 久久成人一区二区| 色噜噜狠狠色综合欧洲selulu| 中日韩一级黄色片| 久久精品这里都是精品| 国产成人涩涩涩视频在线观看| 青青草原av在线| 欧美福利视频网站| 午夜激情在线| 久久99国产精品久久久久久久久| av毛片在线免费看| 欧美日本啪啪无遮挡网站| 亚洲制服国产| 高清一区二区三区日本久| 9765激情中文在线| 青草成人免费视频| 国产一区二区三区影视| 国产精品免费在线免费| 啪啪av大全导航福利综合导航| 国产精品亚洲激情| 久久久久久久久成人| 国产精品sss| 羞羞答答一区二区| 午夜一区二区三区| 99久久精品费精品国产| 成人国产一区二区三区| 亚洲欧洲一区二区天堂久久| 自慰无码一区二区三区| 日韩影院在线观看| 欧美激情第一区| 成人精品小蝌蚪| 欧美日韩高清丝袜| 中文字幕在线播放不卡一区| 99视频只有精品| 午夜精品123| 日本精品入口免费视频| 欧美精品成人一区二区三区四区| 亚洲国产综合网| 亚洲精品视频播放| 日韩精品成人av| 久久久伊人日本| 久久99久久99精品免观看软件| 成人性生交大片免费看小说| 国产成人aa在线观看网站站| 美女三级99| 7777久久香蕉成人影院| 阿v天堂2018| 日本不卡视频一二三区| 99国产精品免费视频| 久久综合成人精品亚洲另类欧美| 四虎影视1304t| 亚洲成在人线免费| 中文字幕在线播放av| 精品av久久707| 欧美成年黄网站色视频| 国语自产在线不卡| 99久久er| 久久精品日产第一区二区三区乱码| 日韩精品久久久久久久电影99爱| 精品一区二区三区无码视频| 日韩中文字幕亚洲一区二区va在线 | 中文字幕一区二区av| 国产一线二线三线女| 日本美女一区二区三区视频| 国产a级片视频| 亚洲国产精品精华液ab| 国产情侣在线视频| 制服丝袜中文字幕一区| 免费在线超碰| 久久久久中文字幕| 91国产精品| 欧美一区二区三区在线播放| 欧美激情综合色综合啪啪| 天天干天天干天天干天天干天天干| 丁香激情综合五月| 天天天天天天天天操| 欧美视频一区二区三区| 天堂v在线观看| 欧美久久久精品| 欧美日韩免费电影| 日韩成人在线资源| 亚洲一区免费| 扒开伸进免费视频| 亚洲精品久久嫩草网站秘色| 欧美成人一区二区视频| 日韩精品视频在线观看免费| 日韩三级免费| 97se在线视频| 国产精品久久久久久久| 在线免费视频a| 国产网站一区二区| 日本中文字幕第一页| 亚洲成人精品久久久| 黄页网站大全在线免费观看| 亚洲伊人第一页| 国产精品7m凸凹视频分类| 爱爱爱爱免费视频| 国产精品午夜在线| 中文永久免费观看| 在线成人激情黄色| 精品无人乱码一区二区三区| 欧美在线视频一区二区三区| 校园激情久久| 国产黄色网址在线观看| 日韩欧美一区视频| 国产免费永久在线观看| 国产大片精品免费永久看nba| 综合色就爱涩涩涩综合婷婷| 久久无码高潮喷水| 国产亚洲自拍一区| 中文字幕a级片| 精品国内亚洲在观看18黄| 999精品视频在线观看| 丰满女人性猛交| 国产成人综合在线观看| 国产一级在线观看视频| 亚洲精品www| 国产超碰精品| 亚洲高清在线播放| 韩国毛片一区二区三区| 99视频只有精品| 亚洲成人精品视频| 91精品产国品一二三产区| 日韩欧美精品一区二区| 久久99精品久久只有精品| 欧美成人精品欧美一| 亚洲精品wwwww| 欧美日韩免费观看视频| 亚洲欧洲一区二区| 国产美女视频91| 自拍偷拍欧美亚洲| 亚洲一区二区久久久| av在线亚洲一区| 少妇人妻在线视频| 国产精品美女视频| 国产www视频| 欧美综合在线观看| 久久婷婷蜜乳一本欲蜜臀| 成年女人免费视频| 在线观看视频91| 日韩av官网| 欧美日韩一区二区三| 精品中文字幕一区二区| 国产在线欧美在线| 亚洲香蕉av在线一区二区三区| 北岛玲精品视频在线观看| 国产无限制自拍| 国产精品免费丝袜| 人妻少妇一区二区三区| 国产精品影片在线观看| 国产一区清纯| 日韩欧美黄色网址| 亚洲高清在线观看| 亚洲在线资源| 日本精品www| 亚洲一区二区偷拍精品| 2019中文字幕在线视频|