CodeQL使用

0x00 环境搭建

CodeQL技术让人眼前一亮,它将代码当作数据来处理,使用类似SQL的语法来查询代码的AST和数据流。本文简单介绍下该工具的使用和基本知识,当作备忘录。

该工具的特点:

  • 将代码当作数据,用SQL查询。
  • 支持多种语言(暂时不支持PHP)
  • 数据流/污点追踪,AST语法树都有。

研究还是看官方文档靠谱,我看过的文档记录下来。

入门QL语法:https://help.semmle.com/QL/learn-ql/introduction-to-ql.html

QL语法手册:https://help.semmle.com/QL/ql-handbook/predicates.html
JAVA QL语法支持:https://help.semmle.com/QL/learn-ql/java/introduce-libraries-java.html.

简单步骤:

需要下载和clone的资源:

0x01 初步使用

CodeQL帮助我们进行了语法树和数据流分析,现在只需要专注于查询语句的写法即可。

例如,通过QL语法可以快速查询出空block:

1
2
3
4
5
import java

from Block b
where b.getNumStmt() = 0
select b, "This is an empty block."

0x02 WebGoat实际测试

最赞的是数据流分析:单文件数据流(local data flow),跨文件数据流(global data flow)。
https://help.semmle.com/QL/learn-ql/java/dataflow.html

选取WebGoat项目来看看Codeql的数据流分析效果。

1. codeql生成数据库

webgoat v.8.0.0.M21之后不支持JDK8,需要checkout换分支。

1
2
git checkout tags/v8.0.0.M21
codeql database create webgoat --language=java

测试项目需要可以mvn编译通过,实际编译脚本为:

1
mvn clean package -f "pom.xml" -B -V -e -Dfindbugs.skip -Dcheckstyle.skip -Dpmd.skip=true -Denforcer.skip -Dmaven.javadoc.skip -DskipTests -Dmaven.test.skip.exec -Dlicense.skip=true

2. QL的SQL注入查询

使用QL库的JAVA安全样例,CWE-089SqlTainted代码,直接跑:

1
2
3
4
5
6
7
8
import semmle.code.java.Expr
import semmle.code.java.dataflow.FlowSources
import SqlInjectionLib
import DataFlow::PathGraph

from QueryInjectionSink query, DataFlow::PathNode source, DataFlow::PathNode sink
where queryTaintedBy(query, source, sink)
select query, source, sink, "Query might include code from $@.", source.getNode(), "this user input"

直接追进去可以看到,定义了标准的source、sink、sanitizer流程~

1
2
3
4
5
6
7
8
9
10
11
private class QueryInjectionFlowConfig extends TaintTracking::Configuration { // 继承了taint tracking,就是全局污点跟踪~ @angelwhu
QueryInjectionFlowConfig() { this = "SqlInjectionLib::QueryInjectionFlowConfig" }

override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }

override predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }

override predicate isSanitizer(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
}
}

其中定义的src需要完善,没有很好的支持Spring Boot的RestController写法。

source、sink样例

成功找出了3个SQL注入,效果可以,优化的空间也有许多。测试代码后续更新到github上。

0x03 参考文档

Codeql整体介绍
Codeql使用介绍

CVE-2018-11776: How to find 5 RCEs in Apache Struts with CodeQL
OGNL injection in Apache Struts: Discovering exploits with taint tracking

文章作者: angelwhu
文章链接: https://www.angelwhu.com/paper/2019/12/30/CodeQL-introduction/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 angelwhu_blog