CodeQL:探索代码安全的利器

图片

01 CodeQL简介

在 2019 年,GitHub 收购了 Semmle,并将 CodeQL 集成到了其平台中,这次收购使得 CodeQL 成为了 GitHub Advanced Security 功能的一部分,通过 GitHub 的 Code Scanning 功能,用户可以轻松地将 CodeQL 集成到他们的开发流程中,实现持续的代码安全检查,通过自动化的安全分析帮助开发者及早发现和修复安全问题。

CodeQL 是一种强大的代码分析工具,它使用一种称为 QL(Query Language)的查询语言来帮助开发者和安全研究人员在代码库中发现潜在的安全漏洞、代码质量问题和合规性问题。

CodeQL 的工作原理

1、抽象语法树(AST):CodeQL 分析引擎首先将代码解析成抽象语法树,这是一种代码的树状结构表示,其中每个节点代表代码中的一个构造(如变量声明、函数调用等)。

2、控制流图(CFG):然后,它构建控制流图,这有助于理解代码的执行路径。

3、数据流分析:通过分析控制流图中的路径,CodeQL 可以追踪数据在程序中的流动,这有助于识别潜在的安全问题,如不安全的用户输入。

4、查询语言(QL):使用 QL 编写的查询语句可以定义要搜索的代码模式,这些模式与安全漏洞或者代码质量相关。

编写的 QL 语句如何执行

1、编写查询:开发者或安全研究人员使用 QL 编写查询,这些查询定义了要搜索的特定代码模式。

2、执行查询:查询可以通过 CodeQL CLI(命令行界面)或集成在 IDE 中的 CodeQL 插件来执行。

3、结果分析:执行查询后,CodeQL 会返回结果,这些结果通常是代码库中与查询模式匹配的所有实例。

4、修复建议:CodeQL 还可以提供修复建议,帮助开发者理解问题所在。

02 CodeQL安装

CodeQL包括两部分:数据文件分析引擎(闭源)和QL规则库(开源)

分析引擎

https://github.com/github/codeql-cli-binaries

规则库

https://github.com/github/codeql

PS:codeql-cli分析引擎和codeql-lib查询规则库的版本要一致,版本不匹配,部分QL查询规则会不匹配,执行后会报错。

图片

首先将下载的二进制分析引擎文件添加到环境变量,再将ql规则库放到在VScode中工作区:把从https://github.com/github/codeql/tags下载的整个QL规则库文件夹放到工作区。

在VScode的CodeQL插件设置分析引擎的路径。

图片

03 QL数据库编译

在CodeQL插件中设置数据库,加载本地编译好的数据库,部分github的项目可以指定github项目地址去自动下载。

图片

获取github编译好的数据库文件(参考文档)

https://docs.github.com/zh/code-security/codeql-cli/getting-started-with-the-codeql-cli/preparing-your-code-for-codeql-analysis#%E4%BB%8E-githubcom

图片

本地项目创建CodeQL数据库,使用codeql database create命令:

<database>指定数据库名、--language指定目标语言:

codeql database create <database> --language=<language-identifier>

假设目标语言为Java,就在codeql-codeql-cli-v2.14.3\java\ql\src\目录新建ql后缀文件编写QL, 其他语言依此类推。

图片

04 QL编写

完整的CodeQL使用指南和QL语法参考官方文档:https://codeql.github.com/

(1)文件上传查询

对于传统的漏洞类型,如SQL注入、RCE、XSS、文件上传、SSRF等等,由于这些漏洞几乎经由相对固定的代码规则触发,CodeQL官方已经积累了诸多常见漏洞代码的QL查询规则,安全人员也在持续向官方库贡献QL查询规则,方便安全人员更快捷的寻找这类漏洞。可以在下载的QL规则文件的\开发语言\ql\src\Security\CWE找到这些规则,不同的CWE文件对应了不同的安全风险。

图片

可以使用如下命令来集中查询当前系统是否存在上述漏洞:

其中:<codeql_db>指定编译好的ql数据库名,--format指定查询结果的保存文件格式,--output指定查询结果的保存文件名

codeql database analyze <codeql_db>  D:\CodeQL\codeql-codeql-cli-v2.14.3\java\ql\src\codeql-suites\java-security-extended.qls --format=csv --output=java-results.csv

根据目标系统的开发语言选择对应目录即可

图片

查找文件上传漏洞:

使用CodeQL的污点跟踪类TaintTracking::Configuration定义sink(危险代码入口)、source(用户可控的入参)。

这里sink就是处理上传文件的upload方法,source使用CodeQL的RemoteFlowSource类型即可(其中包含了大部分的入参类型,不需要再单独定义)。

图片

找到了两处。

图片

漏洞修复的代码增加了一个validateFile方法,用于校验文件合法性,TaintTracking::Configuration中的isSanitizer(净化器)用于检测source传播到sink的过程是否经过指定方法,这个方法用于校验数据合法性,这里就是指校验文件合法性的validateFile方法,将其添加到isSanitizer,如果sink经过了这个validateFile方法,这个漏洞就不再成立。

图片

此时查询结果为空,也就是上传文件会经过合法性校验。

(2)SSRF查询

用户填写的url最后被HttpClientUtil发起请求并回显。

图片

还是用污点跟踪类TaintTracking::Configuration定义sink(危险代码入口)、source(用户可控的入参,查找HttpClientUtil类get、post方法被调用的位置,一共有32处。

图片

图片

(3)垂直越权查询

由于大部分逻辑漏洞没有比较明显的漏洞代码规则,白盒检测不容易直接发掘这类风险。不过使用CodeQL可以批量找到某些类型逻辑漏洞的代码特征,这就可以辅助我们去发掘逻辑类漏洞。在使用CodeQL查找越权漏洞的时候,一种思路是先找到低权限用户能调用的所有服务入口,再看这些服务是否可以操作敏感功能、数据,依此来检查是否存在垂直越权。

假设服务入口使用了shiro做了注解来配置权限,可以先用CodeQL找到所有注解,再进一步找到shiro配置的注解:使用hasQualifiedName()匹配全限定名为org.apache.shiro.authz.annotation.RequiresPermissions的注解即可。

低权限用户能访问的服务是属性为read级别的shiro注解,此时再用关键字read匹配注解名,整个QL只有十来行。

查询显示read级别的服务一共有44个,比挨个服务排查确实要高效一些(一个应用可能有上百个服务入口),再看这些只读权限的接口是否存在低权限用户都可以操作的敏感功能、数据的风险,来进一步找出垂直越权。

如果是自定义的AOP注解,在注解的属性值来配置用户权限,如level为1是应用中用户权限最小值的level,可以先用CodeQL查询level为1的AOP注解,再看这些服务入口是否存在最小权限用户都可以操作的敏感功能、数据。

第一步跟上面查询shiro注解的第一步差不多,只是把Annotation换成了Field,再用hasName()过滤注解类型。

接着再找到值为1的字段,再查询这些字段被定义的位置,也就是配置了这个注解字段值的服务入口。

图片

执行完后一共查到26个level为1的服务,再看这些服务入口是否存在level为1的用户可以操作的敏感功能、数据,这样就能不留遗漏的找到所有垂直越权。

图片

05 常见问题总结

1、Lombok 不能与 CodeQL 的Java 分析器一起使用,因为 lombok 生成的get、ser方法没有包含在CodeQL的数据库中,与 Javac 编译器挂钩的 lombok 注释处理器会动态重写 Javac 的语法树以使它们完整。解决办法:

方法1. 可以参考官方issues来处理

https://github.com/github/codeql/issues/4984

方法2. 使用IDEA的delombok插件处理,更方便

https://zhuanlan.zhihu.com/p/404855643

2、编译CodeQL数据库时,如果提示缺少依赖,可以先将对应依赖注释,注释后一般接着又会提示没有包(之前注释的jar中的包),就把这部分引用依赖的代码也注释,但可能会影响漏洞检测结果准确性。

3、如果遇到项目使用的依赖不在中央仓库,比如使用了腾讯的TSF,此时需要按照TSF的配置说明去修改本地配置文件,然后重新编译项目即可。

4、对于从github获取的CodeQL数据库,这些数据库可能是使用新版本的CodeQL去编译创建的,但我们本地的CodeQL引擎很可能是之前的版本,那当你使用本地的CodeQL去分析这个数据库文件时就会有如下报错,提示这个CodeQL数据库与您尝试运行的查询引用的QL库不兼容,这时只需要重新在本地下载新版本的CodeQL规则库、新版本的CodeQL分析引擎,再重新执行查询即可。

图片

作者:马云卓
2024年7月8日
洞源实验室  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值