CodeQL 入門 - 環境建置

Rainie
職場學習筆記
Published in
8 min readNov 28, 2021

CodeQL 是一套 Github 在 2019 開源且免費的靜態掃描程式碼工具,讓你能在產品 release 前及早發現潛藏的漏洞並提供相對應改善的方法。

CodeQL 有幾項顯著的特色 :

  • 免費且開源
  • 客製化 rule/engine
  • 可以像查詢資料庫一樣,透過程式編寫 query 把資料撈出來

CodeQL 常被拿來跟業界主流的 Fortify 比較,而我們選擇使用 CodeQL ,純粹是兩套我們都沒用過,而 CodeQL 支援 Action 可以直接導入目前的 CI 流程😃

根據其他同事做的評測,他們覺得 Fortify 支援的語言廣泛、在大部分熱門語言能檢測到的漏洞比較多、FA 相對較少。畢竟 Fortify 比 CodeQL 老多了!不過 CodeQL 免費且開源,我相信隨著更多熱心人的貢獻會讓他更加完善。

這篇會介紹如何在 Local 上建置並使用 CodeQL。

Local 架設 CodeQL CLI

Step1. 安裝 CodeQL CLI

這邊選擇安裝泛用性最高的 CLI 版本,如果你有安裝 Chocolatey,輸入choco install codeql就能安裝 CodeQL CLI,預設路徑放在 C:\ProgramData\chocolatey\lib\codeql\codeql

使用 choco 的優點是安裝可透過指令執行且環境變數也會自動設定好,但缺點就是沒特別設定 chocolatey 的話,有些步驟得用 admin 的權限執行。

Step2. 下載 CodeQL queries and libraries

CodeQL 把分析時各種語言會使用到的 queries 和相關的 libraries 獨立成另一個 repo,所以得要把這個 repo clone 一份到 local。因為它的名字跟 CLI 的資料夾同名,為了避免混淆,官方建議在 CLI 同一路徑下 create 另一個資料夾叫做 codeql-repo 來存放。

另外,建議 repo 的版本最好跟 CLI 的版本是一致的,避免執行時產生不相容的問題。

Step3. Create CodeQL Database

CodeQL 的 database 會從你的 code base 裡提取 code 與 code 之間的關係,並建立階層式的架構,包含 syntax tree, data flow graph 等等。這篇我就拿自己之前的 c++ repo 來分析看看會被檢測出什麼 😅

在 CodeQL 的文件中有提到,database 的資料夾不可以事先存在,所以每次重新產生都得把原有的 database 資料夾刪掉。另外針對像是 c++ 這種需要編譯的語言,擷取資料的過程是透過監控專案建置過程而產生的,因此必須在參數裡提供 compiler 的編譯資訊。

我之前的的 c++ 專案,只提供 cmake 生成 msvc 專案的方法,因此這邊就使用 msbuild 來編譯並建立 database :

codeql database create --language=<language> --command=<compile command>// example
codeql database create database --language=cpp --command="msbuild D:\Hash_Algorithm_Evaluation\bin\Hash_Algorithm_Evaluation.sln /t:Hash_Algorithm_Evaluation:rebuild /p:configuration=Release /p:platform=Win32"

create database 有幾個重要的參數 :

  • database - 指定 database 所在路徑,沒指定的話則是當前目錄
  • source-root - 指定 source code 所在路徑,沒指定的話則是當前目錄
  • language - 指定 create database 的語言
  • command - 編譯語言的話,這邊得帶入 compiler 的 build command,以 msvc 專案為例,我是使用 msbuild 去編譯

成功建置後,database 裡面就會長的像下圖這樣,接下來就可以開始分析了!

Step4. QL packs and qls file

在分析之前,先了解一下 QL packs 跟 qls file 的概念

QL packs 是一個將 queries, library files, query suites, metadata 組織起來的 package,裡面包含許多不同分類的 ql file, 每個 ql file 就是一條 query ,他就像一條規則,你可以用來定義分析資料庫時所選用的條件。

除此之外,你也可以使用 QL language 去撰寫自己的 ql file,但這邊就超出本篇的討論範圍了。

每個 QL pack 一定得包含一個 qlpack.ql,用來告訴 CodeQL 如何編譯這些 query 以及相依套件的相關資訊,cpp 的 qlpack.ql 格式如下:

name: codeql/cpp-queries
version: 0.0.2
dependencies:
codeql/cpp-all: "*"
codeql/suite-helpers: "*"
suites: codeql-suites
extractor: cpp
defaultSuiteFile: codeql-suites/cpp-code-scanning.qls

除了使用單一條 query,官方也有提供 suites 版本的 qls file,簡單來說就是規則集的概念,可以定義多條要執行的 query 或是想要 exclude 的條件。

底下的 qls file 是官方提供的 cpp-code-scanning.qls:

- description: Standard Code Scanning queries for C and C++
- queries: .
- apply: code-scanning-selectors.yml
from: codeql/suite-helpers
- apply: codeql-suites/exclude-slow-queries.yml
from: codeql/cpp-queries

而他選擇套用的 code-scanning-selectors.yml 則是下面這樣 :

- description: Selectors for selecting the Code-Scanning-relevant queries for a language
- include:
kind:
- problem
- path-problem
- alert
- path-alert
precision:
- high
- very-high
problem.severity:
- error
- warning
tags contain:
- security
- include:
kind:
- diagnostic
- include:
kind:
- metric
tags contain:
- summary
- exclude:
deprecated: //
- exclude:
query path: /^experimental\/.*/

上面的 tag 像是 kind、precision、problem.seversity ,你都可以在每一個 ql file 的開頭找到相對應的分類。

Step5. 執行 CodeQL queries

接下來,我們就使用官方內建的 qls file 來做分析,指令如下:

codeql database analyze <database> <queries> --format=<format> --output=<output>// example
codeql database analyze D:\Hash_Algorithm_Evaluation\database cpp-code-scanning.qls --format=sarifv2.1.0 --output=cpp-results.sarif
  • database - 欲分析的資料庫路徑
  • queries - 欲用來分析的 ql file,可以包含多個 ql file 或是以 suites 形式組成 qls file
  • format - report 生成的格式
  • output - report 的輸出路徑

分析過程會根據 source code 的複雜程度跟 quires 的多寡而有時間上的差異,編譯完成後會產出一份 sarifv 的檔案,如果你有使用 vs code ,你可以下載 sarifv viewer 來顯示,接下來就可以根據這份報告把漏洞補起來囉!

我也是前陣子剛碰 CodeQL 的初心者,如果這篇文章有任何刊誤,都歡迎底下留言告訴我,我會即時修正!有任何 CodeQL 的使用小技巧也歡迎跟我分享 😃

Ref

--

--