zoukankan      html  css  js  c++  java
  • Java自动化审计(上篇)

    Java自动化审计(上篇)

     

    本文是 i 春秋论坛作家「Wker」表哥分享的技术文章,文章旨在为大家提供更多的学习方法与技能技巧,文章仅供学习参考。

    CodeQl

    CodeQL是一个免费开源的代码语义分析引擎(GitHub购买之后的开源项目),其利用QL语言对代码、执行流程等进行“查询”,以此实现对代码的安全性白盒审计,进行漏洞挖掘。

    靶场

    在网上找到的一个简单的靶场,spring的项目,使用的jdk1.8。

    CodeQl安装

    到目前为止,CodeQl已经更新到v2.7.3版本。

    1、下载CodeQl;

    2、放入环境变量:export PATH=/Home/CodeQL/codeql:$PATH、source /etc/profile,方便我们后期使用vscode插件;

    3、下载codeql sdk;

    4、下载codeql vsc插件:

    Java自动化审计(上篇)

     

    只需要几步下载就可以完成CodeQl环境的部署。

    生成CodeQl数据库

    CodeQl并不提供语法树解析,只是提供对外查询的接口,所以我们需要给他生成database帮助其进行查询(这里检测的是我在网上clone下的靶场)。

    codeql database create databasePath  --language="java"  --command="mvn clean install --file pom.xml" --source-root=sourcePath
    

    databasePath:数据库路径(要保存到那)

    sourcePath:源文件代码存放路径

    执行完之后就会生成对应的数据库,这里需要注意mvn的路径问题。

    测试语句

    1、首先用vscode打开codeql sdk,在ql/java/ql/src下创建一个test.ql来编写测试脚本。

    2、在codeql选项卡中打开之前创建的数据库。

    3、在test.ql中编写select "hello word",右击选择执行ql,选择测试的数据库。

    如果执行完毕之后出现如下界面,则说明环境搭建完毕。

    Java自动化审计(上篇)

     

    到此为止就可以在test.ql下编写检测脚本了。

    CodeQl语法

    和sql语句很类似,可以通过AST视图查看到当前数据库中的内容:

    Java自动化审计(上篇)

     

    这里简单介绍基本的使用方法:

    from [datatype] var
    where condition(var = something)
    select var
    

      

    对应下面的:

    from int i
    where i = 1
    select i
    

      

    第一行指定的变量,第二行条件判断,第三行输出内容。

    类库可以通过查看AST中的内容进行确定。

    名称

    解释

    Method

    方法类,Method method表示获取当前项目中所有的方法。

    MethodAccess

    方法调用类,MethodAccess call表示获取当前项目当中的所有方法调用。

    Parameter

    参数类,Parameter表示获取当前项目当中所有的参数。

    这只是举例说明,例如下面这段代码:

    import java
    
    from Method method
    select method
    

      

    可以查询出当前项目的所有方法。

    下面这段是存在过滤的代码:

    import java
    
    from Method method
    where method.hasName("getStudent")
    select method.getName(), method.getDeclaringType()
    

      

    查找名称为getStudent的方法和对应的类。

    并且codeql提供了一种谓词的方法帮助来分割复杂的逻辑代码:

    import java
    
    predicate isStudent(Method method) {exists(|method.hasName("getStudent"))}
    
    from Method method
    where isStudent(method)
    select method.getName(), method.getDeclaringType()
    

      

    详细的语法内容可以参考:https://codeql.github.com/docs/codeql-language-guides/basic-query-for-java-code/

    污点分析

    污点分析可以抽象成一个三元组〈sources, sinks, sanitizers〉的形式。其中,source即污点源,代表直接引入不受信任的数据或者机密数据到系统中;sink即污点汇聚点,代表直接产生安全敏感操作(违反数据完整性)或者泄露隐私数据到外界(违反数据保密性);sanitizer即无害处理,代表通过数据加密或者移除危害操作等手段使数据传播不再对软件系统的信息安全产生危害。

    污点分析就是分析程序中由污点源引入的数据是否能够不经无害处理,而直接传播到污点汇聚点,如果不能说明系统是信息流安全的;否则,说明系统产生了隐私数据泄露或危险数据操作等安全问题。

    简单的理解是,source参数输入的位置,sink危险函数执行的位置,sanitizers过滤函数。

    通过定义上述三点内容可以定位出一条参数传递链,当然sanitizers可以不存在。

    设置source

    通过override predicate isSource(DataFlow::Node src) {}设置source,这是大多常用的source入口,包括spring的也在其中。

    设置sink

    override predicate isSink(DataFlow::Node sink) {
    exists(Method method, MethodAccess call |
      method.hasName("query")
      and
      call.getMethod() = method and
      sink.a**pr() = call.getArgument(0)
    )
    }
    

      

    上述代码是一个谓语,查询方法名为query的方法。

    当然,目前检测的是SQL注入,所以当jdbc执行query方法,则为进入了sink。

    Flow数据流

    from VulConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
    where config.hasFlowPath(source, sink)
    select source.getNode(), source, sink, "source"
    

      

    通过config.hasFlowPath(source, sink)设置source和sink,这样codeql就可以帮助自动检测漏洞,检索调用链。

    测试

    import java
    import semmle.code.java.dataflow.FlowSources
    import semmle.code.java.security.QueryInjection
    import DataFlow::PathGraph
    
    class VulConfig extends TaintTracking::Configuration {
      VulConfig() { this = "SqlInjectionConfig" }
    
      override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
    
      override predicate isSink(DataFlow::Node sink) {
        exists(Method method, MethodAccess call |
          method.hasName("query")
          and
          call.getMethod() = method and
          sink.a**pr() = call.getArgument(0)
        )
      }
    }
    
    from VulConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
    where config.hasFlowPath(source, sink)
    select source.getNode(), source, sink, "source"
    

      

    上述是拷贝的他人写好的,代码也是上面所讲,运行之后就可以看到所有进入query方法的链路了。

    Java自动化审计(上篇)

     

    可以点击对应的source和sink查看位置,可以看到codeql已经帮我们整理出了5条调用链。

    一步步跟踪第一条调用链,可以得出完整的调用链路:

    indexLogic.getStudent(username);
    indexDb.getStudent(username);
    String sql = "select * from students where username like '%" + username + "%'";
    jdbcTemplate.query(sql, ROW_MAPPER);
    

      

    至此,简单的SQL注入就能查询得到。

    以上为今天分享的内容,小伙伴们看懂了吗?

  • 相关阅读:
    vue父组件props参数太大时子组件created取不到数据-解决方法
    uniapp-高德地图Android+IOS appkey申请与使用
    用iframe解决jquery.js和prototype.js的冲突
    iview-project 改写页面 title
    iview-project-3.0安装记录
    用live2d给你的博客放个二次元看店娘
    vue全局公共函数
    微信h5页面下拉露出网页来源的解决办法
    Java ConcurrentModificationException 异常分析与解决方案
    Java注释@interface的用法【转】
  • 原文地址:https://www.cnblogs.com/ichunqiu/p/15766065.html
Copyright © 2011-2022 走看看