引言
CodeQL是一个代码分析平台,在它的帮助下,安全研究人员可以利用已知的安全漏洞来挖掘类似的漏洞。在本文中,我们首先为读者介绍与代码分析平台CodeQL有关的一些基本概念,同时,还会为实例方式为读者展示了如何编写和运行QL语言编写的简单代码。
CodeQL基本概念
漏洞挖掘范式
我们知道,在挖掘漏洞的时候,最少有两条路可走:对于高手来说,可以硬怼,就像艺术家,可以直接在纸上作画。我们不妨将这种范式称为画葫芦范式。这条路的优点是,有可能挖到0 day,缺点是对研究人员的要求较高,换句话说,就是对新手不太友好。不过,大家也不要灰心,因为还有另一条路可走:照葫芦画瓢。也就是说,我们可以参考已知的漏洞,在我们自己的目标代码中查找类似的安全隐患,从而降低上手的难度,提高工作效率。我们不妨将这种范式称为画瓢范式。
实际上,本文介绍的代码分析平台CodeQL与相应的查询语言QL就是为第二种范式而生的,下面我们将为读者分别加以介绍。
CodeQL平台
简单来说,CodeQL就是一种代码分析平台。借助这个平台,安全研究人员可以实现变种分析的自动化。这里所谓的变种分析,就是以已知的安全漏洞作为参照物,在我们的目标代码中寻找类似的安全问题的过程,也就是上面所说的照葫芦画瓢的过程。
为了便于理解,我们可以将CodeQL跟MySQL进行简单的类比。MySQL是一个数据库管理系统,可以用来存储、管理和分析数据;而CodeQL则可以看作是一个代码库管理系统,用于存储、管理和分析代码。类似的,为了分析数据,我们需要SQL语言来查询数据库;而为了分析代码,这里则需要利用QL语言来查询代码库。
此外,为了提高安全分析人员的工作效率,CodeQL平台还提供了许多有用的工具、脚本、查询和代码库。
QL语言
QL是一种通用的、面向对象的语言,可以用来查询任何类型的数据。在CodeQL平台上面,为了帮助安全研究人员完成各种代码分析工作,提供了许多现成的查询和代码库——这些都是使用QL语言编写的,并且,它们都是开源的,源码可以从这里(https://github.com/semmle/ql)下载。
CodeQL数据库
CodeQL数据库中存放的是使用CodeQL创建和分析的关系数据。 我们可以将其看作是QL的快照,但是针对CodeQL工具进行了相应的优化处理。
我们的第一个QL程序
QL简介
QL是一种查询语言,该语言的功能非常强大,例如,通过在CodeQL平台上执行QL语言编写的查询,可以帮助我们挖掘代码中各种安全漏洞的变体。因此,在使用CodeQL进行代码分析之前,学习QL的基本语法是很有必要的。
由于QL是一种逻辑编程语言,自然会涉及各种逻辑公式,因此,会用到常见的逻辑连接词(例如and、or和not)、量词(例如forall和exists)以及其他重要的逻辑概念,如谓词等。
此外,QL还支持递归和聚合。这使得我们可以通过简单的QL语法来编写复杂的递归查询,并直接使用诸如count、sum和average之类的聚合操作。
查询:QL程序的运行结果,还是QL程序本身?
大家需要注意的一点是,查询(query)有时候指的是QL程序的运行结果,而有时候则是表示QL程序本身,这个需要大家根据上下文进行区分。例如,上面说过,CodeQL平台为我们许多现成的查询和代码库,这里的“查询”,指的就是用QL语言编写的程序。
hello world
现在,让我们来编写一个最简单的查询:通过select子句返回字符串“hello world”。为了方便起见,这里将使用LGTM——我们可以简单把它看成是CodeQL平台的云版本。为此,需要首先打开查询控制台(https://lgtm.com/query),具体如下所示:
在运行查询之前,需要选择该查询(即QL程序)要处理的语言和项目,就这里来说,我们可以随便选。实际上,打开控制台后,就提示我们选择相应的语言,我们可以通过下拉菜单选择语言:
比如,我们可以选择Python语言。这时,查询控制台将自动填充如下所示的查询:
如上图所示,控制台自动添加了如下所示代码:
import python select "hello world"
其中,“import python”表示这里查询的代码是用Python语言;而“select "hello world"”表示返回字符串“hello world”。熟悉SQL语言的读者可能有点眼熟,因为这里用到了select语句。实际上,尽管QL语言与SQL语言有许多相似之处,但是两者之间还是有差别的。
眼尖的读者可能已经发现了,在上图中,查询控制台提示我们选择相应的项目。同样的,我们也可以通过下拉菜单进行选择:
为了方便起见,这里直接选择查询控制台提供的演示项目,这样我们就不用登录了。之后,点击右边出现的绿色“Run”按钮,来运行我们的QL代码:
稍等片刻之后,原来的“Run”按钮会被一个紫色的“View results”按钮,点击该按钮,我们就可以看到查询结果了:
感兴趣的读者可以修改select语句后面的字符串,看看控制台的输出结果会有何变化。
为了便于读者理解上面的代码,下面我们来简单介绍一下select语句的用法。
select语句简介
在编写查询模块(通俗点说,就是QL程序)时,select语句通常位于文件的末尾,其一般格式如下所示:
from /* ... 变量声明... */ where /* ... 逻辑公式 ... */ select /* ... 表达式 ... */
其中,from和where子句是可选的,就像上面的例子中看到的那样。为了帮助读者理解,下面我们举一个全面一点的例子:
from int x, int y where x = 6 and y = 7 select x + y
在这里,我们首先定义了两个整型(int)变量:x和y。然后,在where子句后面的逻辑公式给两个变量赋值,最后,利用select语句返回两个变量的和。读者可以利用查询控制台运行上述代码,具体如下所示:
这时,我们将会得到如下所示的结果:
小结
CodeQL是一个代码分析平台,在它的帮助下,安全研究人员可以利用已知的安全漏洞来挖掘类似的漏洞。在本文中,我们首先为读者介绍与代码分析平台CodeQL有关的一些基本概念,同时,还通过动手的方式为读者如何编写并运行QL语言编写的代码。
备注:本系列文章乃本人在学习CodeQL平台过程中所做的笔记,希望能够对大家有点滴帮助——若果真如此的话,本人将备感荣幸。
参考资料:https://help.semmle.com/