CodeQL 作为 github 开发的 AST 辅助工具 其给出了完善的指引 例如这项挑战:https://securitylab.github.com/ctf/go-and-dont-return/. 这项挑战旨在探索 Go 语言中的控制流漏洞。参与者需要分析一段 Go 代码,找出其中可能导致安全问题的控制流缺陷。这不仅能帮助开发者更好地理解 Go 语言的特性,还能提高他们识别和修复潜在安全漏洞的能力。

既然他们写了 Participants do not need prior knowledge of CodeQL 那我就从零开始 跟随这项挑战给出的项目要求 看看在完成以后能不能学到一点 CodeQL 的用法

# Setup instructions

  1. 使用 VSCode
  2. Clone this:vscode-codeql-starter & Read readme- - 这不就是 prior knowledge 吗 Update:🙇道歉 原来只是模板
  3. 下载目标代码库

那就从给出的 starter 代码库来吧

经历了与网络 vscode github 激烈的搏斗 终于成功设置好了 codeql 插件 下载目标仓库以后 codeql 启动!

# Step 1: Let’s catch the bug!

# Step 1.1: Finding references to ErrNone

In this first step, you’ll find all references to  ErrNone  in your code. Write the query that finds all identifiers named  ErrNone .

这里的题目要求找出所有的 identifiers 所以应该用 Ident 这个 Expressions 并用 getname 获取它的 name=errnone

import go
//Finding references to ErrNone
from Ident id
where id.getName() = "ErrNone"
select id

image.png

成功查到了 231 个结果

# Step 1.2: Finding equality tests against ErrNone

In this next step, write a query to find all equality test expressions where one of the operands is an identifier called  ErrNone . Your query should give you 158 results.

要我们找出所有有一端是 errNone 的相等判断

应该使用 ComparisonExpr 来获取 并使用 getLeftOperand()  and  getRightOperand() 看看是不是 ErrNone

import go
from ComparisonExpr equality
where equality.getLeftOperand().toString() = "ErrNone" or equality.getRightOperand().toString() = "ErrNone"
select equality

image.png

# Step 1.3: Finding if-blocks making such a test

Write a query that finds all if statements, where the condition is an equality test similar as found in step 1.2.

要寻找 if 语句 if 是一个语句 所以要用 ifstmt 寻找 if 语句节点 再用 getCond 拿到它的条件表达式

基于上面的相等表达式修改:

import go
from ComparisonExpr equality, IfStmt ifstmt
where (equality.getLeftOperand().toString() = "ErrNone" or equality.getRightOperand().toString() = "ErrNone") and ifstmt.getCond() = equality
select ifstmt

我一开始很疑惑啊 这能过编译检查的?

也是成功拿到 133 个结果

# Step 1.4: Finding return statements

找返回语句 这个简单

import go
from ReturnStmt ret
select ret

# Step 1.5: Finding if-blocks without return statements

Write a query that finds all if-blocks that don’t contain return statements in their  then  branch.

拿到所有返回空或不返回的 if 块

通过 ifstmt.getThen ().getAStmt () 来获取 找到所有的 then 分支的 stmt 再做匹配

import go
//Write a query that finds all if-blocks that don’t contain return statements in their then branch. 
from IfStmt ifstmt
where not exists(ReturnStmt returnstmt |
    returnstmt = ifstmt.getThen().getAStmt()
)
select ifstmt

# Step 1.6: Putting it all together

Combine steps 1.5 and 1.3 and write a query that finds the if-blocks testing for equality to  ErrNone  with no return.

那就缝合一下

import go
from IfStmt ifstmt, ComparisonExpr equality
where not exists(
    ReturnStmt rs | rs = ifstmt.getThen().getAStmt()) and ((equality.getLeftOperand().toString() = "ErrNone" or equality.getRightOperand().toString() = "ErrNone") and ifstmt.getCond() = equality)
select ifstmt

# Step 2: Improving the precision

# Step 2.1: Find conditionals that are fed from calls to isReqAuthenticated

Write a data flow configuration that tracks data flowing from any call to  isReqAuthenticated  to any equality test operand. Your query must select all equality tests -- Type:  DataFlow::EqualityTestNode  -- where the operand is a  sink  of the above configuration.