codeQl入门学习 (一)
0 条评论快速开始
参考胜哥文章CodeQL从入门到放弃
有一点注意下,在mvn编译的时候本地出错了,我修改了pom.xml为下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.l4yn3</groupId>
<artifactId>micro-service-seclab</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>micro-service-seclab</name>
<description>seclab</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/fluent-hc -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>fluent-hc</artifactId>
<version>4.5.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp/okhttp -->
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--添加配置跳过测试-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
<!--添加配置跳过测试-->
</plugins>
</build>
</project>
后续学习也参考文章中的项目。
codeql语法的学习(学的有点杂,我都不知道在学啥)
类
PrimitiveType 是一个原始类型,包括boolean, byte, char, double, float, int, long, short,他们所有的原始类型为void与
我们用程序分析,Variable 为咱们编译程序中的所有变量,打印一下
import java
from Variable v
select v
我们找到这些变量为int型的,
import java
from Variable v, PrimitiveType pt
where pt = v.getType() and
pt.hasName("int")
select v
为啥没有String类型的,因为java当中,string不是基本类型,而是一个class对象。
我们可以用下面语法找到类型为String的变量
import java
from Variable v, Class cla
where cla = v.getType() and
cla.hasName("String")
select v
看到的确是找到了类型为String的变量
当然 codeql提供了非原始类型,RefType
import java
from Variable v, RefType rt
where rt=v.getType() and rt.hasName("String")
select v
RefType 包含4个子类,这些都可以查到。
Class
代表一个 Java 类。Interface
代表一个Java接口。EnumType
代表一个javaenum类型。Array
表示 Java 数组类型。
java中还有同一个文件中声明两个类的,这样第二个类的名称与其编译的名称就不一样,
TopLevelType
表示在编译单元的顶层声明的引用类型
使用如下语法查询
import java
from TopLevelType tl
where tl.getName() != tl.getCompilationUnit().getName()
select tl
codeql官方有案例,案例
java中还有类中声明类的,可以用以下语法查询
import java
from NestedClass nc
where nc.getASupertype() instanceof TypeObject
select nc
java中还有泛型
GenericInterface 用来表示一个泛型类型声明
java.util.Map就是一个泛型类,我们用以下语法来查询参数实例化了java.util.Map,ParameterizedType是所有参数的类型
import java
from GenericInterface map, ParameterizedType pt
where map.hasQualifiedName("java.util", "Map") and
pt.getSourceDeclaration() = map
select pt
如果从程序中找到实例化了map的参数可以用下面语法来查询
import java
from Variable v, RawType rt
where rt = v.getType() and
rt.getSourceDeclaration().hasQualifiedName("java.util", "Map")
select v
getSourceDeclaration 可以获取相应泛型类型
变量
在上面,我们用Variable 来查询程序中所有的类,有时需要更具体的,所以codeql提供了3个子类
Field
代表一个 Java 字段。LocalVariableDecl
表示局部变量。Parameter
表示方法或构造函数的参数。
试一下Field
import java
from Field fd
select fd
查询到的是
LocalVariableDecl
Parameter
抽象语法树
抽象语法树AST是一个程序的抽象表示模式,各种程序的语句都可以被抽象成节点,比如跳转节点,return节点,switch节点等等,通过节点还可以生成程序流程图等等,在数据流分析中十分重要。
比如跳转节点
import java
from Stmt s
where s.getParent() instanceof IfStmt
select s
元数据
这里关注下注解,我们在测试springboot项目比较注意这些
比如找到方法上的所有注解
import java
from Method m
select m.getAnAnnotation()
函数调用
我们可以用Call来找到所有表达式中的调用部分
import java
from Call c
select c
找到所有调用了println方法的Call
import java
from Call c, Method m
where m = c.getCallee() and
m.hasName("println")
select c
总结
可以看出codeql对程序拆分的十分细致,其强大的功能不仅可以通用分析程序,我们自己还可以安装想法设计规则,可以感觉它是一款很适合的代码审计辅助工具,值得学习。