author:平安银行应用安全团队@xsser
大背景 在CodeQL出来之前,我们拥有的静态代码扫描工具常见为:fortify,checkmarks,sonar,findbugs,pmd等,这些工具的特色有一些是基于静态的ast结构,例如pmd,纯静态的ast解析的工具存在误报多,无法追踪漏洞等致命的问题,而findbugs之类存在堆栈跟踪有限的情况,checkmarks的数据流又存在跟踪不全无法定义构造特定情况下的数据流的情况,重点是还要钱! 在这个情况下, CodeQL 在2 019 年年底,即疫情爆发之际 由微软发布了此工具。经过数月的研究发现,这个工具功能异常强大,其底层的图数据库非常好,可以编写自己描述的规则来寻找对应的数据流从而实现漏洞定位,甚至数据安全的一些实践。故把研究成果分享给大家,希望大家可以从中受益! 实现关联接口、入参、和危险方法并自动化构造payload
![723b3ba24169da0ef2403a0d1a9755c0.png](https://i-blog.csdnimg.cn/blog_migrate/600f2528f0a5e8791fc394e226485e51.jpeg)
1
CodeQL介绍
CodeQL 是一个史诗般质的跨越的工具,在这个之前,大家公认的顶峰可能是 fortify 。QL是一种查询语言,支持对C++,C#,Java,JavaScript,Python,go等多种语言进行分析,可用于分析代码,查找代码中控制流等信息。
2
认识基础模块
首先引入1个模块,这个模块也是 CodeQL 的核心之一,那就是 DataFlow 模块。这个模块负责实现代码的数据流跟踪功能,即实现整个的调用栈分析。 这个模块最核心常用的方法就是 hasFlowPath 方法,它接受2个参数,一个是 source,另 一个是 sink ,这个模块是用来判断一个数据流,所以我们可以这样写代码:from QueryInjectionSink query, DataFlow::PathNode source, DataFlow::PathNode sink where queryTaintedBy(query, source, sink)selectquery, source,sink
其中queryTaintedBy是一个“谓词”,通俗的说就是方法。这个方法里我们会去操作数据流的config配置。
按照上述写法就可以查询source到sink的数据流了。但直接这样查当然是不行的,我们还要约束一定的范围和条件,这里的QueryInjectionSink就是这个查询的配置,也就是config,它必须继承于TaintTracking::Configuration,所以我们要建立一个数据类型来表示这个
class QueryInjectionFlowConfig extends TaintTracking::Configuration {
//定义配置 this可以随意写 QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }//定义source的来源,这里是来自RemoteFlowSource,这是一个官方写的class,较为全面的定义了远程可控的来源,但是还是有一些问题。我做了一些补充,以后会提及 override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }//QueryInjectionSink定义了sink的约束条件 override predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }//过滤条件,这里对node中的数据类型做了判断,如果是一些int long之类的数据类型就会抛弃不会进入数据流判断,这也是CodeQL较为准确的识别SQL注入的原因之一。 override predicate isSanitizer(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType or node.getType() ins