初探 CodeQL 自动化代码分析(一)

实际需求

之前分析了两个Apache Kylin 框架的rce漏洞代码层原理,从正向到逆向地尝试探讨了漏洞发现者是如何发现这些漏洞的,

当时得出的结论是,可以通过找寻敏感的函数名,方法名,类名,锁定这些内容的位置之后,

从代码层面上,一步步逆推到参数传入的地方,然后再分析是否存在利用链。

但是这种方法难度较大,除了要掌握大量敏感函数、方法、类等信息,还需要对每一种框架结构有一定的了解,此外还要手动找到每一个潜在切入点。

所以我在想是否有一种自动化工具能帮我们完成这个过程,简化代码审计的工作量?

CodeQL 在很大程度上就可以简化上述的工作。

.

.

什么是 CodeQL ?

CodeQL 本质是一个代码分析引擎,使用它的时候,代码会被当作数据处理。

既然把它当成了一种数据,那么被当做数据的代码可以像查询mysql数据库一样被查询。

所有的bug,安全漏洞,或者某些错误代码都可以被查询出来(前提是查询语句要正确),这个过程本质上和查询mysql中userid为某一个值的过程没有区别。

而这里关键的一点就是CodeQL的查询语句,你可以运行GitHub研究人员和社区贡献者编写的标准CodeQL查询,或者编写你自己的查询语句来用于自定义分析。

.

总结一下 CodeQL 干的事:

  • 把要分析的代码准备好(通过建立 CodeQL 数据库 database)
  • 对这个建立好的数据库执行 CodeQL 查询语句
  • 输出查询结果

.

在这篇文章中,不会有太多关于自定义分析的语句的内容,目前主要是介绍一下 CodeQL 的基础用法,从搭建到使用别人写好的查询语句进行分析尝试。

.

.

搭建环境与安装

使用 CodeQL 的时候可以选择两种方式

  • 命令行模式 CLI (Command Line Interface)
  • Visual Studio Code 插件

.

虽然使用 VScode 插件比命令行更加方便,且功能也多一点,

但是我认为掌握命令行模式也很重要。

因为有时候项目文件太大导致静态代码的数据库太大,此时往往会放到服务器上去跑,那么图形化界面的优势就少了。

而且命令行模式本质其实和 VScode插件一样的,掌握命令行可以更好地理解VScode中插件都干了什么事

.

.

命令行模式安装

首先直接下载 CodeQL 引擎

https://github.com/github/codeql-cli-binaries/releases/tag/v2.7.3

image-20220517174631683

选择对应系统版本,我这里使用的是 Debian10,选择codeql-linux64.zip

这个文件可以看作是 CodeQL 的核心引擎,它是不开源的(所以是BINARIES)

下载完成之后解压,

建议设置好目录,因为 CodeQL默认搜索上级目录和当前目录,文件目录层级清晰一些有利于核心引擎查找它需要的文件

我把它放在了自定义的 CodeQL 目录

image-20220517174718891

之前提到过,有了核心引擎还不够,还需要查询语句等,可以把这类文件看作一个仓库

仓库里包含了查询语句,一些依赖,包,这些东西都是codeql分析C、C++、C#、Java、JavaScript、Python、Ruby等代码数据库时需要的

(注意go语言代码数据库所需要的仓库是需要另外下载的)

所以一个完整的codeql包括核心引擎和仓库

下载仓库,地址如下

proxychains4 git clone –recursive https://github.com/github/codeql.git

注意加入 –recursive 选项把全部子模块都下载了

最后将这个目录改名为 codeql_repo (目录原来默认为 codeql,改名主要是为了目录结构清晰)

关键一点是要将这个目录放到刚才下载核心引擎目录的同级目录

image-20220517174756637

这里有一点要注意的,如果下载了 go 语言的代码仓库,那么要把目录放至与核心引擎同一级

如下:

image-20220517174836175

以上都做好后,开始配置环境变量,目的是为了在任意处使用codeql

vim ~/.zshrc

在最下面填入下面内容

export PATH=$PATH:/data/CodeQL/codeql_cli

/data/CodeQL/codeql_cli 换成你 codeql* 或者 codeql.cmd 的目录

最后是验证 codeql 安装是否成功, 在任意目录执行一下两条命令:

codeql resolve languages (显示可以用来被创建代码数据库的语言有哪些)

codeql resolve qlpacks (显示哪一些qlpacks可以被codeql命令行工具找到,qlpacks就是查询语句的包)

如下图就成功安装

image-20220517174913805

image-20220517174933659

.

.

命令行模式构建代码数据库

要对代码进行分析,首先要将代码构建为一个代码数据库database,而构建数据库的命令如下:

codeql database create –languages=

  • 写你要创建的代码数据库的路径,且注意不能是已经存在的目录

  • :

    写语言标识符,分析的代码是什么语言就选择什么标识符

image-20220517174955944

  • 基本参数选项如上,还有几个参数

  • –source-root :

    创建数据库时使用的主要源文件的根目录路径。默认情况下,该命令假定当前目录是源文 件的根目录–使用该选项可以指定一个不同的位置。

  • –db-cluster :

    可以用来创建多语言代码数据库

  • –command :

    使用一种或多种编译型语言创建数据库时使用,

    如果指定语言只有Python和JavaScript这种非编译型语言,则省略。

    主要是用来加入编译器的 build command 的

    (如果省略,codeql会自动检测并使用自己的工具来编译创建 )

  • –no-run-unnecessary-builds:

    与-db-cluster一起使用,来抑制CodeQL CLI不需要监控构建的语言

    (例如,Python和JavaScript/TypeScript)的构建命令。

    代码分为编译型语言和非编译型语言,使用 codeql 构建不同类型的代码数据库的时候也有所不同。

    而编译型语言在创建代码数据库的时候codeql会监视整个过程

.

.

命令行构建Java项目的代码数据库

首先随便从网上下载一个Java 项目,最好别太大

我选择的是这个:某博客项目

https://github.com/saysky/ForestBlog.git

\2.

之后进入到该项目中找到 pom.xml

使用如下命令构建代码数据库

codeql database create java-database –language=java –command=’mvn clean install’

也可以省略掉后面 –command 选项,让codeql 用它内置的编译器

创建成功之后如下:

image-20220517175024931

image-20220517175044461

除了自己通过源码构建代码数据库,还可以直接从 LGTM 这个网站上下载一些开源项目的代码数据库,

https://lgtm.com/projects/g/apache/kafka?mode=list

直接下载之后就可以使用 codeql 查询探测这个代码数据库中是否有漏洞了

可以省去codeql构建代码数据库的过程

.

.

基础 codeqld 探测语法

创建成功代码数据库之后就要使用查询语句进行漏洞探测

基础语法:

codeql database analyze –format= –output=

  • :

    构建好的代码数据库的存放目录

  • –format :

    输出结果文件的格式,可以是CSV,SARIF,图表形式

  • –output :

    输出结果文件的路径

  • :

    写你想要使用的查询语句,可以是一个或者多个单独的查询语句文件。

    或者是一个装有查 询语句文件的目录。

    如果不选这个的话,codeql会根据代码数据库的语言默认使用对应的 查询语句

  • –threads :

    设置线程数量,默认为1。线程越多查询结果输出越快

.

.

实例演示漏洞探测

使用下面命令即可开始对博客项目代码漏洞探测,

codeql database analyze /构建项目代码数据库的路径 –format=csv –output=./result –threads=5

结果如图:

image-20220517175110219

.

image-20220517175127462

.

.

总结

codeql 可以更好帮助我们进行代码审计,当遇到一个项目源代码的时候,如果不清楚其架构,甚至对其语言没有足够的了解,可以先尝试使用该工具进行探测。

网上大部分资料介绍的都是使用codeql是通过VScode插件来使用的形式,

但命令行模式下的codeql使用,更加适合批量地对大批源码进行探测,放在服务器上跑也不需要考虑图形化界面带来的不便。

codeql的核心点在于选择或者编写适合的查询语句(文件),后续的文章会以VScode的方式介绍如何用查询语句,并尝试对一个已知漏洞的代码进行审计

.

.

./