codeQL使用(一)

codeQL使用

环境搭建

建议看视频代码审计CodeQL-1_哔哩哔哩_bilibili

简单来说就是官方下载包github/codeql: CodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security,vscode安装并配置插件,完成

使用文档

详情参考文档:

CodeQL documentation (github.com)

为 CodeQL 分析准备代码 - GitHub 文档

初始化

创建数据库

codeql database create ./xxx.db --language=xxx --source-root=源码目录

codeql database create ./untitle_3rm1.db --language=javascript --source-root=D:\study\source\2022.9\0CTF_Tctf\3rm1\untitled_3rm1

有些时候如java需要lib库的,要加command参数运行一下mvn安装依赖

CodeQL database create  quartz_db --language="java"  --command="mvn clean install --file pom.xml -Dmaven.test.skip=true"

image-20240307173126316

也可以--overwrite对原有数据库进行覆盖

vscode插件选中数据库

image-20240307165424721

选择语言

image-20240307170128789

可以在这个目录下创建codeql脚本

image-20240307171507154

随后编写脚本,如

import java

from Class c
where c.getASupertype().hasName("InvocationHandler")
    and
    c.getASupertype*() instanceof TypeSerializable
select c

右键运行,右边可以查看结果

点击 view AST,可以查看语法树

image-20231031143742669

ERROR: Could not detect a suitable build command for the source checkout.

如果碰到这个问题,可能是
由于构造codeql数据库的时候,需要对源代码进行编译,这里应该是需要mvn等编译工具的命令在环境变量中。

调试jdk

由于没法直接反编译出jdk源码,所以用网上现成的库

https://blog.csdn.net/mole_exp/article/details/122330521

在这里下一个就好

调试各种依赖jar

工具:

https://github.com/waderwu/extractor-java  下载在codeql上一级目录下了
https://github.com/ttonys/CodeQLAnalyseJar

https://github.com/waderwu/extractor-java 示例

假如直接用jar解压再反编译成java这个方式还没吃过,所以直接需要什么jar就去网上(github)搜索源码

难点在于整个合适(包含所需依赖)的数据库 + 写语法

image-20240326114028579

就建在这个目录下

image-20240326114242504

随后写脚本运行,等待,有亿点卡(耗内存的)

调试github

一般就是看到网上已经有现成数据库拿下来用的场景

比如说看到github :https://github.com/apache/activemq

image-20240408122300753

接着会让你选语言

image-20240408122425058

加载成功如下

image-20240408131605638

快速启动

image-20240408131622109

创建查询

可以用这个快捷开始

image-20240408131622109

这里可以新建查询

image-20240408141317129

查询结果如右边视图,默认是这个

image-20240408141923908

alert内容和select不一样

image-20240408141757420

如果找到任何匹配的代码,请单击列中的链接以在代码查看器中ma查看表达式。

image-20240408142109610

语法学习和练习

基本语法

Here is an example of a basic query:

select "hello world"

This query returns the string "hello world".

More complicated queries typically look like this:

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

For example, the result of this query is the number 42:

from int x, int y
where x = 6 and y = 7
select x * y

Note that int specifies that the type of x and y is ‘integer’. This means that x and y are restricted to integer values. Some other common types are: boolean (true or false), date, float, and string.

官方习题

参考

Introduction to QL — CodeQL (github.com)

Exercise 1 - Strings

Write a query which returns the length of the string "lgtm".

字符串处理函数:QL language specification — CodeQL (github.com)

答案

import java
select "lgtm".length()

Exercise 2 - Numbers

Write a query which returns the sine of the minimum of 3^5 (3 raised to the power 5) and 245.6.

数字处理:QL language specification — CodeQL (github.com)

直接算3^5是这样,

import java
from int x,int y
where x = 3 and y = 5
select x.pow(y)

但float可能比较不了所以还是换一个类型

答案

import java
from float x,float y,float z
where x = 3 and y = 5 and z = 245.6
select z.minimum(x.pow(y)).sin()

官方答案

from float x, float y
where x = 3.pow(5) and y = 245.6
select x.minimum(y).sin()

Exercise 3 - Booleans

Write a query which returns the opposite of the boolean false.

答案

import java
select false.booleanNot()

Exercise 4 - Dates

Write a query which computes the number of days between June 10 and September 28, 2017.

import java
from date a, date b
where a = "10/6/2024".toDate() and b = "28/9/2024".toDate()
select a.daysTo(b)

Example query with multiple results

比如说找10以内勾股数

from int x, int y, int z
where x in [1..10] and y in [1..10] and z in [1..10] and
      x*x + y*y = z*z
select x, y, z

image-20240408161607854

有多个结果,就会以行的方式增加;有多个字段,则以列的形式增加

为了重用性和简洁,我们可以自定义类(结构体)和函数

class SmallInt extends int {
  SmallInt() { this in [1..10] }
  int square() { result = this*this }
}

from SmallInt x, SmallInt y, SmallInt z
where x.square() + y.square() = z.square()
select x, y, z

Find the thief - exist的妙用

情景:Find the thief — CodeQL (github.com)

直接 import tutorial 开始做题

 import tutorial
 from Person t
 where t.getHeight() > 150 and t.getAge()>30 and t.getHairColor() = "brown"
    and not t.getLocation() = "north"
    and (t.getHairColor() = "brown" or t.getHairColor() = "black")

 select t

这个例子教会我们一些条件的使用,and or not的逻辑连接词的使用

有个秃头问题还是很有意思,比如某个函数没有xxx方法,也可以套用这个例子

情景:

调查一群人,已知小偷头发不是金色,有getHairColor()函数

很容易写出这样

where t.getHairColor() = "brown" or t.getHairColor() = "black"
或者
where not t.getHairColor() = "blond"

如果小偷是秃头怎么办?在这种情况下,小偷没有头发,因此getHairColor()谓词根本不返回任何结果!

所以正难则反,先找出有头发的(有xxx方法的)

from Person t, string c
where t.getHairColor() = c
select t

请注意,我们只是暂时引入了该变量c,并且在子句中根本不需要它select。在这种情况下,最好使用exists

from Person t
where exists(string c | t.getHairColor() = c)
select t

那秃头就是not exists

合起来

t.getHairColor() = "brown" or t.getHairColor() = "black" or not exists( string colorh | t.getHairColor() = colorh)

还有个chrick,不是最大和最小=》存在一个人比他大

exists(Person p | p.getAge() > t.getAge())

Catch the fire starter - 谓词和类

Read the examples below to learn how to define predicates(谓词) and classes(类/结构体) in QL.

这一次,您只需要考虑一个特定的村民群体,即居住在村庄南部的村民。您可以定义一个新的谓词 isSouthern,而不是在所有查询中都写getLocation() = "south ":

predicate isSouthern(Person p) {
  p.getLocation() = "south"
}

You can now list all southerners using:

/* define predicate `isSouthern` as above */

from Person p
where isSouthern(p)
select p

如果多个条件就这么写(就是把where抄过来,and or)

predicate isCountry(string country) {
  country = "Germany"
  or
  country = "Belgium"
  or
  country = "France"
}

predicate hasCapital(string country, string capital) {
  country = "Belgium" and capital = "Brussels"
  or
  country = "Germany" and capital = "Berlin"
  or
  country = "France" and capital = "Paris"
}

所以说谓词里面可以放各种比较

如果还想进一步简化,不引入传Person的过程,可以使用class

import tutorial
predicate isShouther(Person p) {
   p.getLocation() = "south"
 }
class Souther extends Person{
   Souther(){
      isShouther(this)
   }

}

from Souther s
select s

Crown the rightful heir-传递闭包

Crown the rightful heir — CodeQL (github.com)

CodeQL官方教程中几道QL练习题 - 简书 (jianshu.com)

国王死了,没有子嗣,需要寻找一个有血缘的人继承它的财富和权力,或者是需要找一个和他有共同祖先的亲戚

此时只有ParentOf()函数,需要如何定义出一个亲戚函数?

找一个和他有共同祖先的亲戚:就是a的ParentOf()的ParentOf()的ParentOf()...=b的ParentOf()的ParentOf()的ParentOf()

如果想通了可以用递归返回祖先,因为祖先要么是我的ParentOf(),要么是这个函数返回值的ParentOf()

Person ancestorOf(Person p) {
  result = parentOf(p) or
  result = parentOf(ancestorOf(p))
}

但是递归不好理解,好在这种递归由于在codeql里面较为常用(称为传递闭包)

所以有两个专门的符号:

parentOf+(p) applies the parentOf() predicate to p one or more times. This is equivalent to ancestorOf(p).
parentOf*(p) applies the parentOf() predicate to p zero or more times, so it returns an ancestor of p or p itself.

也就说最后变成

Person relativeOf(Person p) {
  parentOf*(result) = parentOf*(p)
}

最终答案

import tutorial

Person isRelated(Person p){
   parentOf+(p) = parentOf+(result)
}

from Person p
where p = isRelated("King Basil") and
   not p.isDeceased()
select p

课外题

第一个问题:村里发色最多的一种是哪种颜色

import tutorial

class HairColor extends string{
   HairColor(){
      exists(Person p | p.getHairColor() = this )
   }
   int ct(){
      result = count(Person p | p.getHairColor() = this | p)
   }

}

from HairColor h
where not exists(HairColor h1 |h1.ct()>h.ct()) 
select h, h.ct()

答案是brown

第二个问题:每个地区发色最多的一种是哪种颜色

/**
 * This is an automatically generated file
 * @name Hello world
 * @kind problem
 * @problem.severity warning
 * @id java/example/hello-world
 */

import tutorial

class Location extends string{
   Location(){
      this in ["east", "west", "south", "north"]
   }
}

class HairColor extends string{
   HairColor(){
      exists(Person p | p.getHairColor() = this )
   }
   int ct(){
      result = count(Person p | p.getHairColor() = this | p)
   }

   int locationCt(Location loc){
      result = count(Person p | p.getHairColor() = this and p.getLocation() = loc | p)
   }

}

from Location location, HairColor h
where h.locationCt(location) = max(HairColor c1 | | c1.locationCt(location) )
select h, h.locationCt(location), location

答案

image-20240807184851913

但是我下面是这样写的

from Location location, HairColor h
where not exists(HairColor h2 | h2.locationCt(location) > h.locationCt(location))
select h, h.locationCt(location), location
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇