初探 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
选择对应系统版本,我这里使用的是 Debian10,选择codeql-linux64.zip
这个文件可以看作是 CodeQL 的核心引擎,它是不开源的(所以是BINARIES)
下载完成之后解压,
建议设置好目录,因为 CodeQL默认搜索上级目录和当前目录,文件目录层级清晰一些有利于核心引擎查找它需要的文件
我把它放在了自定义的 CodeQL 目录
之前提到过,有了核心引擎还不够,还需要查询语句等,可以把这类文件看作一个仓库
仓库里包含了查询语句,一些依赖,包,这些东西都是codeql分析C、C++、C#、Java、JavaScript、Python、Ruby等代码数据库时需要的
(注意go语言代码数据库所需要的仓库是需要另外下载的)
所以一个完整的codeql包括核心引擎和仓库
下载仓库,地址如下
proxychains4 git clone –recursive https://github.com/github/codeql.git
注意加入 –recursive 选项把全部子模块都下载了
最后将这个目录改名为 codeql_repo (目录原来默认为 codeql,改名主要是为了目录结构清晰)
关键一点是要将这个目录放到刚才下载核心引擎目录的同级目录
这里有一点要注意的,如果下载了 go 语言的代码仓库,那么要把目录放至与核心引擎同一级
如下:
以上都做好后,开始配置环境变量,目的是为了在任意处使用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就是查询语句的包)
如下图就成功安装
.
.
命令行模式构建代码数据库
要对代码进行分析,首先要将代码构建为一个代码数据库database,而构建数据库的命令如下:
codeql database create
–languages=
: 写你要创建的代码数据库的路径,且注意不能是已经存在的目录
: 写语言标识符,分析的代码是什么语言就选择什么标识符
基本参数选项如上,还有几个参数
–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 项目,最好别太大
我选择的是这个:某博客项目
\2.
之后进入到该项目中找到 pom.xml
使用如下命令构建代码数据库
codeql database create java-database –language=java –command=’mvn clean install’
也可以省略掉后面 –command 选项,让codeql 用它内置的编译器
创建成功之后如下:
除了自己通过源码构建代码数据库,还可以直接从 LGTM 这个网站上下载一些开源项目的代码数据库,
直接下载之后就可以使用 codeql 查询探测这个代码数据库中是否有漏洞了
可以省去codeql构建代码数据库的过程
.
.
基础 codeqld 探测语法
创建成功代码数据库之后就要使用查询语句进行漏洞探测
基础语法:
codeql database analyze
–format= –output=
: 构建好的代码数据库的存放目录
–format :
输出结果文件的格式,可以是CSV,SARIF,图表形式
–output :
输出结果文件的路径
: 写你想要使用的查询语句,可以是一个或者多个单独的查询语句文件。
或者是一个装有查 询语句文件的目录。
如果不选这个的话,codeql会根据代码数据库的语言默认使用对应的 查询语句
–threads :
设置线程数量,默认为1。线程越多查询结果输出越快
.
.
实例演示漏洞探测
使用下面命令即可开始对博客项目代码漏洞探测,
codeql database analyze /构建项目代码数据库的路径 –format=csv –output=./result –threads=5
结果如图:
.
.
.
总结
codeql 可以更好帮助我们进行代码审计,当遇到一个项目源代码的时候,如果不清楚其架构,甚至对其语言没有足够的了解,可以先尝试使用该工具进行探测。
网上大部分资料介绍的都是使用codeql是通过VScode插件来使用的形式,
但命令行模式下的codeql使用,更加适合批量地对大批源码进行探测,放在服务器上跑也不需要考虑图形化界面带来的不便。
codeql的核心点在于选择或者编写适合的查询语句(文件),后续的文章会以VScode的方式介绍如何用查询语句,并尝试对一个已知漏洞的代码进行审计
.
.
./