codeql 下一个靶场来测试
https://github.com/l4yn3/micro_service_seclab/
引擎安装(codeql)
https://github.com/github/codeql-cli-binaries/releases
SDK安装(ql)
https://github.com/github/codeql
codeql database create D:\Data\secquan\Audit\CodeQl\databases\micro_service_seclab_database --language="java" --command="mvn clean install --file pom.xml" --source-root=D:\Download\micro_service_seclab-main --overwrite
D:\Data\secquan\Audit\CodeQl\databases\micro_service_seclab_database 这个是要生成数据库的路径 D:\Download\micro_service_seclab-main 这个是要生成的项目路径
如果直接执行百分之八十会报错,原因是maven没有编译成功,因此我们先去idea成功编译再去创建数据库
第一个错误 jdk版本不对
第二个错误,测试时出现问题
添加这个插件
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <testFailureIgnore>true</testFailureIgnore> </configuration> </plugin>
成功构建
我们接着构建数据库
codeql database create D:\Data\secquan\Audit\CodeQl\databases\micro_service_seclab_database --language="java" --command="mvn clean install --file pom.xml" --source-root=D:\Download\micro_service_seclab-main --overwrite
成功Successfully
生成好的数据库
打开ql文件夹
导入数据库
注意目录创建demo.ql文件
运行
没运行成功就重写导入一下数据库吧
查找所有方法
import java from Method method select method
查看ast
import javafrom Method method where method.hasName("getStudent" ) select method.getName() , method.getDeclaringType()
谓词
import javapredicate isStudent (Method method) { exists( | method.hasName("getStudent" ) ) } from Method method where isStudent (method) select method.getName(),method.getDeclaringType()
起始点
import javaoverride predicate isSource (DataFlow::Node src) { src instanceof RemoteFlowSource }
终点
import javaoverride predicate isSource (DataFlow::Node src) { src instanceof RemoteFlowSource } override predicate isSink (DataFlow::Node sink) { exists(Method method,MethodAccess call | method.hasName("query" ) and call.getMethod() = method and sink.asExpr() = call.getArgument(0 ) ) }
在代码中的寻找点就是
jdbcTemplate.query(sql, ROW_MAPPER);
确定是否连通
import javafrom VulConfig config ,DataFlow::PathNode source,DataFlow::PathNode sink where config.hasFlowPath(source,sink) select source.getNode(),source,sink,"source"
CodeQL语法和java类似,extends代表继承父类TaintTracking::Configuration 这个类是官方提供用来做数据流分析的通用类,提供了很多数据流分析相关的方法,比如isSource(定义source),isSink(定义sink) src instanceof RemoteFlowSource表示src必须是RemoteFlowSource类型.在RemoteFlowSource里,官方提供了非常全的source定义,我们本次用的Springboot的Source就已经覆盖了.
import javaimport semmle.code.java.dataflow.FlowSourcesimport semmle.code.java.security.QueryInjectionimport DataFlow::PathGraphclass VulConfig extends TaintTracking ::Configuration{ VulConfig() { this = "SqlIjectionConfig" } override predicate isSource (DataFlow::Node src) { src instanceof RemoteFlowSource } override predicate isSink (DataFlow::Node sink) { exists(Method method , MethodAccess call | method.hasName("query" ) and call.getMethod() = method and sink.asExpr() = call.getArgument(0 ) ) } } from VulConfig config,DataFlow::PathNode soucre,DataFlow::PathNode sink where config.hasFlowPath(soucre, sink) select soucre.getNode(),soucre,sink,"source"
这里已经检测到sql注入了,但是还存在误报 这里是一个long的参数,所以并不存在注入
override predicate isSanitizer (DataFlow::Node node) { node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType or node.getType() instanceof NumberType }
如果当前节点是上面提到的基础类型,那么污染链将被截断
import javaimport semmle.code.java.dataflow.FlowSourcesimport semmle.code.java.security.QueryInjectionimport DataFlow::PathGraphclass VulConfig extends TaintTracking ::Configuration{ VulConfig() { this = "SqlIjectionConfig" } override predicate isSource (DataFlow::Node src) { src instanceof RemoteFlowSource } override predicate isSink (DataFlow::Node sink) { exists(Method method , MethodAccess call | method.hasName("query" ) and call.getMethod() = method and sink.asExpr() = call.getArgument(0 ) ) } override predicate isSanitizer (DataFlow::Node node) { node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType or node.getType() instanceof NumberType or exists ( ParameterizedType pt | node.getType() = pt and pt.getTypeArgument(0 ) instanceof NumberType) } } from VulConfig config,DataFlow::PathNode soucre,DataFlow::PathNode sink where config.hasFlowPath(soucre, sink) select soucre.getNode(),soucre,sink,"source"
连接
isAdditionalTaintStep方法是CodeQl的类TaintTracking::Configuration提供的方法,它的原型是
override predicate isAdditionalTaintStep(DataFlow::Node node1,DataFlow::Node node2){}
他的作用是将一个可控节点A强制传递给另外一个节点B,那么节点B也就成了可控节点
这里漏了一个sql注入 原因可能是Optional这种类型的使用没有在codeql的语法库里