现阶段Android运用代码漏洞扫描工具品种繁多,实际效果参差不齐,这种专用工具有一个共同的特点,都在运用打包完成之后对运用开展解压扫描仪。这类扫描仪有显而易见的缺陷,扫描仪时间较短,不可以向开发人员即时意见反馈代码上存在安全问题,而且对于难题代码定位必须手动式检索配对源码,这个就更不益于开发人员针对问题代码开展及时地改动。Code Arbiter正是为了解决以上几个问题而研发的,专业对Android Studio里的源码开展网络检测。
1 背景介绍
为完成对Android Studio里的源码开展扫描仪,最简单的形式就是将漏洞扫描工具以IDE插件的方式进行工作中。这时一个自然而然的念头就是从头开始构建一个Android Studio插件,可是开展认真的评定后就会发现,这么做难度系数并很大:
- 工作强度大,很多专业知识要学习,如IDE对外开放API插口、插件UI搭建等,与此同时很多最底层控制模块必须重新搭建;
- 插件的稳定、检测问题精确性上都不一定可以达到已经有开源工具效果。
所以我们继而选择在已经有系统漏洞检测插件的基础上拓展,以满足要求。通过调查,从而入选的2款检测插件是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中获取外部存储文件夹地址的方法主要包含以下这些方法:
getExternalCacheDir()
检测的形式就是,一旦发现存有该方法的启用,则作为一个情况进行汇报,完成详细代码如下所示:
public class ExternalFileAccessDetector extends OpcodeStackDetector { private static final String ANDROID_EXTERNAL_FILE_ACCESS_TYPE = \"ANDROID_EXTERNAL_FILE_ACCESS\"; private BugReporter bugReporter; public ExternalFileAccessDetector(BugReporter bugReporter) { this.bugReporter = bugReporter;
此类的建立是承继OpcodeStackDetector类,是FindBugs中的一个内部类,封装形式了针对获取代码特殊参数方法启用。sawOpcode方法主要参数可以看作待检测代码行号码,根据printOpCode(seen)能够打印出该代码行具体内容。Constants.INVOKEVIRTUAL表明这家银行启用类的实例方法,Constants.INVOKESTATIC表明调用类的静态数据方法。getNameConstantOperand方法表明获取被启用方法的名字,getClassConstantOperand方法表明获取调用类的名字,getSigConstantOperand方法表明获取方法的所有主要参数。bugReporter.reportBug用以汇报检测过的系统漏洞信息内容,在其中BugInstance的三个主要参数各自表明:检测器、系统漏洞种类、系统漏洞级别,在其中系统漏洞级别分成五个等级,如下所示表所显示:
名字 | 主要参数 | 含意 |
---|---|---|
HIGH_PRIORITY | 1 | 高风险风险性 |
NORMAL_PRIORITY | 2 | 中危风险性 |
LOW_PRIORITY | 3 | 低危风险性 |
EXP_PRIORITY | 4 | 安全提醒 |
IGNORE_PRIORITY | 5 | 可忽视风险性 |
addClass、addMethod、addSourceLine用以特定该系统漏洞所属的类、方法、行,便捷汇报系统漏洞时精准定位重要代码。
2.2 逐方法查验
逐方法查验最先获取待检测类全部内容,随后对类里的方法开展逐一查验,一般用于对方法体开展检测,其达到的方法主要通过重新写过visitClassContext方法,下边以对Android TrustManager的空达到的检测为例子做出说明。
TrustManager的空完成,主要指针对检测Server端资格证书是不是可信的方法checkServerTrusted,是不是空完成。下边展现难题代码,假如是空完成那样可能导致手机客户端接受随意资格证书,进而造成数据加密后HTTPS信息被中介人破译。
@Overridepublic void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
检测的方法是根据遍历类中所有方法,找到checkServerTrusted方法,对方法总体开展检测,确认其是不是为空完成,一部分代码如下所示:
public class WeakTrustManagerDetector implements Detector {
classContext.getJavaClass用以获取全部类全部内容;javaClass.getMethods用以获取此类中所有方法,以一个方法目录的方式回到;classContext.getMethodGen用以获取该方法内容;isEmptyImplementation将方法内容导进该功能开展检测,用以明确方法是不是空完成,该方法的代码如下所示:
private boolean isEmptyImplementation(MethodGen methodGen){ boolean invokeInst = false; boolean loadField = false; for (Iterator itIns = methodGen.getInstructionList().iterator();itIns.hasNext();) {
该方法主要运用于检测方法中是否包含方法启用、域实际操作,要是没有包括则称之为一个空达到的方法。因而该方法针对只包括 return true/false 句子的方法体一样称之为一个空完成。
2.3 污渍剖析
数据流分析主要运用于剖析特殊方法载入的主要参数是否能被用户控制,即开展污渍剖析。做污渍剖析首先要界定污染物(source点),污染物可以看作能被用户控制的录入数据,这儿界定的Android污染物主要包含消费者的键入、Intent传入的信息,下边展现界定的那一部分污染物(source点):
- EditText
界定好污染物以后就必须明确环境污染的触发点(sink点),可以看作会开启风险操控的函数公式。界定sink点的形式主要有两种,一种是立即文本文件中导进,以指令引入为实例,代码如下所示:
public class CommandInjectionDetector extends BasicInjectionDetector { public CommandInjectionDetector(BugReporter bugReporter) { super(bugReporter);
从代码中能够很清楚的见到其导进方式就是承继BasicInjectionDetector类,然后此类的结构方法中以loadConfiguredSinks方法,导进包括sink点文件,下边展现该实例文档里面的内容:
java/lang/Runtime.exec(Ljava/lang/String;)Ljava/lang/Process;:0
另一种是自定导进,其完成是由遮盖BasicInjectionDetector类中的getInjectionPoint方法,以WebView.loadurl方法为例子,实例代码如下所示:
@Override
根据创建对象InjectionPoint类结构新的sink点,其结构方法中的第一个参数表明该方法接受环境污染数据信息参数位置,如方法为webView.loadUrl(url),其第一个参数就是new int[]{0},其他的依此类推。
上报发觉系统漏洞的现象,也可通过遮盖getPriorityFromTaintFrame方法的完成,实例代码如下所示:
@Override
根据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中。
private Map<String, List<Location>> get_line_location(Method m, ClassContext classContext){
以后获取Exception包裹的范畴,FindBugs其中包含对Exception的模型,因而可以通过其实体模型能直接获取其范畴并储存到一个页面上,代码如下所示,其中exceptionTable[i].getStartPC用以获取try catch 的起始代码行,exceptionTable[i].getEndPC用以获取try catch 的完毕代码行。
public int[] getExceptionScope(){ try {
对其代码开展一行行检查时,由于应用了最初class文件方式,所以需要限制其遍历的范畴,限制的方法是根据代码的号码,即图中中每排代码的第一个标值。首先要获取代码总公司数的大小,获取的形式就是分析FindBugs模型后第一行代码,寻找关键字code-length后边的标值,即是代码的个数,分析代码如下所示:
public int get_Code_Length(String firstLineCode){ try{
最终对代码开展一行行遍历,遍历中为避免try catch块被遍历到,应用号码来限定遍历的范畴。检测代码行是否包含根据Intent获取参数,及这家银行是不是被try catch 包囊,假如以上两个条件均被开启,那就作为一个情况进行上报。实例代码如下所示,其中get_code_line_index方法用以获取代码的号码,获取的方法是提取代码行首标识符的标值,来确认是不是在代码包裹的范围之内。
private void analyzeMethod(JavaClass javaClass, Method m, ClassContext classContext) throws CFGBuilderException {
3 申请注册装包
上边详尽叙述了怎样结构自身的问题检测代码,进行检测方法的书写后,下一步便是在环境变量上对检测方法进行申请,才能让检测代码运行下去。
必须在2个文档中进行申请,第一个是findbugs.xml,申请注册实例如下所示:
<Detector class=\"com.h3xstream.findsecbugs.android.LocalDenialOfServiceDetector\" reports=\"LOCAL_DENIAL_SERVICE\"/>
在其中Detector用以申请注册该检测方法位置以及唯一标识,BugPattern用以对检测出情况进行分类,便捷展现,这般处分类到”Android安全隐患”中,那在生成报告时问题要被分类到”Android安全隐患”中。
第二个是messages.xml申请注册,申请注册实例如下所示,该申请注册主要是针对此问题做出说明,包含难题的危害性及修补方法。
<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编码普遍安全隐患;
- 提升系统漏洞检测标准,提升检测的精确性,降低乱报。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。