CodeQL學習——自定義查詢


在CodeQL CLI中使用自定義查詢

為了使用CodeQL進行定制分析,我們可以通過自己編寫查詢來實現查找漏洞或錯誤。CodeQL的查詢類型有:

  • 告警查詢:突出顯示代碼中特定位置的問題的查詢。
  • 路徑查詢:代碼中source和sink之間信息流的查詢。

基本查詢結構

用CodeQL編寫的查詢文件擴展名為.ql,並包含一個select子句。許多現有查詢都包含其他可選信息,並具有以下結構:

/**
 *
 * Query metadata
 *
 */

import /* ... CodeQL libraries or modules ... */

/* ... Optional, define CodeQL classes and predicates ... */

from /* ... variable declarations ... */
where /* ... logical formula ... */
select /* ... expressions ... */

import語句

每個查詢通常包含一個或多個import語句,這些語句定義了要導入到查詢中模塊庫和模塊提供了一種將相關類型謂詞用於描述組成QL程序的邏輯關系和其他模塊組合在一起的方法然后,查詢可以訪問您導入的每個庫或模塊的內容。

From子句

from子句聲明查詢中使用的變量。每個聲明必須采用 <type> <variable name>的形式

Where子句

where子句定義了適用於該from子句中聲明的變量以生成結果的邏輯條件該子句使用聚合謂詞和邏輯公式將目標變量限制為較小的集合,這些集合滿足已定義的條件

Select 子句

select子句指定要顯示的變量,這些變量需符合where子句中定義的條件select子句的有效結構由元數據中指定的@kind屬性定義

告警查詢(@kind problem)的Select子句由兩“列”組成,其結構如下:

select element, string
 element:查詢標識的代碼元素,用於定義顯示告警的位置。
 string:一條消息,其中還可以包含鏈接和占位符,說明生成告警的原因。
您可以修改 select 語句最后一欄中定義的告警消息,使用有關鏈接或占位符,提供通過查詢所找到的告警或路徑的更多詳細信息。

編寫查詢元數據

每個查詢文件都是以查詢元數據作為開始,它為用戶提供有關查詢的信息,並告訴CodeQL CLI如何處理查詢結果。

我們在使用database analyze命令進行查詢時,必須包括以下兩個屬性,以確保得到正確的查詢結果:

  • 查詢標識符(@id):是一串小寫字母或數字,通過/-分隔構成的單詞序列,用於識別和分類查詢。
  • 查詢類型(@kind):標識查詢是告警(@kind problem)還是路徑(@kind path-problem)。

元數據屬性

所有查詢文件都支持以下屬性:

屬性 描述
@description <text> 用一段簡單的話描述查詢的目的以及查詢結果的重要性。該描述以純文本編寫,並使用單引號(')將代碼括起來。
@id <text> 是一串小寫字母或數字,通過/-分隔構成的單詞序列,用於識別和分類查詢。每個查詢必須具有唯一的 ID。為確保這一點,對每個ID使用固定的結構可能會有所幫助。例如,標准LGTM查詢具有以下格式:<language>/<brief-description>
@kind

problem
path-problem

標識查詢是告警(@kind problem)還是路徑(@kind path-problem)。有關這些查詢類型的更多信息,請參見關於CodeQL查詢
@name <text> 定義查詢標簽的語句。該名稱以純文本形式編寫,並使用單引號(')將代碼括起來。
@tags

correctness
maintainability
readability
security

這些標簽將查詢按大類分組在一起,以使其更易於搜索和識別。除了此處列出的常用標簽外,還有許多更具體的類別。有關更多信息,請參閱《 查詢元數據樣式指南》
@precision

medium
high
very-high

表示查詢結果為“真肯定”(相對於“假肯定”結果)的百分比。這與@problem.severity屬性一起確定默認情況下是否在LGTM上顯示結果。
@problem.severity

error
warning
recommendation

定義查詢生成的任何警報的嚴重性級別。這與@precision屬性一起確定默認情況下是否在LGTM上顯示結果。

對於過濾器查詢的其他屬性

過濾器查詢用於定義其他約束,以限制其他查詢返回的結果。篩選器查詢必須具有與@kind要篩選其結果的查詢相同的屬性。不需要其他元數據屬性。

例子

一個標准的Java查詢元數據:

image0

有關查詢元數據的更多示例,請參見GitHub存儲庫中的標准CodeQL查詢。

定義查詢結果

您可以通過修改查詢的select語句來控制分析結果在源代碼中的顯示方式。

概述

告警查詢必須在元數據中定義@kind problem屬性。有關更多信息,請參見CodeQL查詢的元數據select 語句最基本的形式必須包含兩“列”:

  • Element ——查詢所標識的代碼元素。這定義了告警的位置。
  • String——為該代碼元素顯示的消息,描述了生成告警的原因。

編寫一個select語句

我們以一個使用標准CodeQL CodeDuplication.qll庫識別相似文件的簡單查詢作為示例。

基本select語句

import java import external.CodeDuplication from File f, File other, int percent where similarFiles(f, other, percent) select f, "This file is similar to another file." 

這個基本的select語句有兩列:

  1. 顯示告警的元素:f對應於File
  2. 要顯示的字符串消息: "This file is similar to another file."

基本選擇語句的結果

 

包含相似文件的名稱

select語句定義的告警信息是固定的,不能給用戶提供太多信息。由於查詢識別出了相似文件(other),因此很容易擴展select語句以告知用戶這些相似文件的名稱。例如:

select f, "This file is similar to " + other.getBaseName() 
  1. Element和之前一樣為f
  2. String"This file is similar to "—字符串文本與相似文件的文件名通過getBaseName()拼接在一起

擴展選擇語句的結果

盡管這比原始的select語句提供了更多信息,但用戶仍然需要手動查找其他文件。

添加鏈接到相似文件

您可以在告警信息中使用占位符以插入其他信息,例如,指向相似文件的鏈接。占位符使用$@定義,並使用select語句的后兩列中的信息來填充。例如,下述select語句就返回了4列信息:

select f, "This file is similar to $@.", other, other.getBaseName() 
  1. Element:和之前一樣為f
  2. 字符串消息:"This file is similar to $@."——該字符串包含一個占位符,它將顯示接下來兩列的合並內容。
  3. 占位符元素:other對應於相似文件。
  4. 占位符的字符串文本:other.getBaseName()所返回的短文件名

顯示告警消息時,$@占位符將替換為根據該select語句定義的第三第四列內容創建的鏈接。

如果使用$@在說明信息中多次使用占位符標記,則第N個使用的$@將由2N+2列2N+3列組成的鏈接代替。如果附加列數量多於占位符標記,則末尾的列將被忽略。相反,如果附加列數量少於占位符標記,則末尾的$@標記將被視為普通文本,而不是占位符。

增加文件相似程度的一些細節

我們可以更進一步,更改select語句以報告兩個文件中相似的內容部分,因為這部分信息已經在查詢中可用。例如:

select f, percent + "% of the lines in " + f.getBaseName() + " are similar to lines in $@.", other, other.getBaseName() 

由於此處添加的新元素不需要是可單擊的,因此我們可以將它們直接拼接到字符串信息中。

結果顯示相似程度


創建一個自定義的QL包

  我們編寫的查詢應該保存在自定義QL包文件夾或其子目錄中。QL包用來整理在分析時使用的文件,包括查詢、庫文件、查詢套件和重要的元數據。QL包目錄的根目錄下必須包含一個以qlpack.yml命名的文件,該文件包含name、version以及libraryPathDependencies字段屬性。如果這個包還包含查詢套件,可以使用suites這個字段來指定其位置。
  執行命令的時候,codeql會掃描其安裝目錄或者子目錄查找qlpack.yml文件,文件中的元數據會告知codeql如何編譯查詢、依賴什么庫以及查詢套件所在的位置。
  例如一個自定義C++查詢和庫的QL包的qlpack.yml文件可能包含以下內容:

name: my-custom-queries
version: 0.0.0
libraryPathDependencies: codeql-cpp
suites: my-custom-suites

其中codeql-cpp是codeql倉庫中用於C/C++分析的QL包的名稱。
QL包包含的其它內容(codeql分析時使用的查詢和庫文件)與qlpack.yml放在同一個目錄,或者它的子目錄中。
例如,一個包含如下文件目錄的QL包,如果需要導入CustomSinks.qll只需要在包的任意目錄聲明:

import mycompany.java.CustomSinks

qlpack.yml
mycompany/
  java/
    security/
      CustomSinks.qll
Security/
CustomQuery.ql

我們可以通過如下方式使用自定義的查詢:

codeql database analyze xssdb E:\codeql\codeql-repo\customql\java\xss.ql --format=sarif-latest --output=result.sarif
codeql database analyze xssdb E:\codeql\codeql-repo\customql\java\xss.ql --format=csv --output=codeql.csv

 



 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM