赞
踩
上篇讲解啦codeql的基础开发环境配置, 本章主要讲解基础语法
codeql database create [编译后的数据库生成路径] --language=java --command="mvn clean install --file pom.xml" --source-root="./apps/WebGoat"
-l,--language=<lang> 创建数据库的语言
-s,--source-root=<dir> 项目的源代码路径,默认为当前路径
-j,--threads=<num> 生成数据库使用的线程数,默认为1
-M,--ram=<MB> 使用多大内存执行生成命令
-c.--command=<command> 构建项目使用的命令,如maven项目使用mvn clean package等
--overwrite 覆盖之前生成的数据库,如果不加上该命令,若存在同名数据库,则报错。
# python项目
codeql database create --language=python <output-folder>/python-database
# 指定优先提取器创建
codeql database create --language=go testdb --search-path ../build/codeql-extractor-go
# 使用以下内容构建的 C/C++ 项目make
codeql database create cpp-database --language=cpp --command=make
# CODEQL_EXTRACTOR_GO_BUILD_TRACING=on使用环境变量构建的 Go 项目
CODEQL_EXTRACTOR_GO_BUILD_TRACING=on codeql database create go-database --language=go
# 使用 Gradle 构建的 Java 项目
codeql database create java-database --language=java --command='gradle --no-daemon clean test'
# 使用 Maven 构建的 Java 项目
codeql database create java-database --language=java --command='mvn clean install'
# 自定义编译脚本,创建数据库
codeql database create new-database --language=<language> --command='./scripts/build.sh'
codeql database analyze --ram=8000 --threads=4 --format="sarif-latest" --output="./results/sql.json" ./databases/java-sec-database ./CWE-089/SqlTainted.ql
解释:
--ram=8000 & --threads=4 分析使用的内存和线程数
--format=<format> (必填) 输出结果的格式,如sarif-latest可以输出json格式,csv输出csv格式
--output="./results/sql.json" (必填) 输出结果路径
./databases/java-sec-database (必填) 分析的数据库路径
./CWE-089/SqlTainted.ql (必填) 使用的查询语句
测试
# 测试单个文件:
codeql dataset check testdb/db-go
codeql query run ../ql/test/test.ql --database=testdb --output=test.bqrs --search-path ..
codeql bqrs decode test.bqrs --format=csv --output=test.csv
diff -w -u <(sort test.csv) expected.csv
# 测试单个文件:
codeql database analyze ../basic/basic.testproj --format=dot nodeGraph.ql --output=outdir --rerun
dot -Tpdf -O outdir/test-plot-cfg.dot
open outdir/test-plot-cfg.dot.pdf
# 测试所有自带安全ql
codeql database analyze python_test ../../workenv/codeql/lib/python/ql/src/Security/* --format=sarif-latest --output=python-results.json
# 测试ql/python/ql/src/Functions/下所有ql文件
codeql database analyze <python-database> ../ql/python/ql/src/Functions/ --format=sarif-latest --output=python-analysis/python-results.json
非污点跟踪
MethodAccess :调用的方法表达式
Method : class中的方法
getCaller :方法调用所在的方法,换句话说是哪个方法体中调用的
getCallee: 被调用的方法
hasName(param):限定名称
getDeclaringType():获取此变量的类型
hasQualifiedName("package","class"):限定类名
样例:
/** * @name JNDI lookup with user-controlled name * @description Performing a JNDI lookup with a user-controlled name can lead to the download of an untrusted * object and to execution of arbitrary code. * @kind problem * @problem.severity error * @precision high * @id java/jndi-injection * @tags security * */ import java from MethodAccess methodAccess where methodAccess.getMethod().hasName("lookup") and methodAccess.getMethod().getDeclaringType().hasQualifiedName("javax.naming", "Context") select methodAccess,methodAccess.getCaller().getName() /* 注释 在使用命令行解析或vscode的时候,必须包含以下两个注释:(参考query-metadata-style-guide) @kind 定义查询的类型,可以定义的类型为以下3个 problem:必须两列或其倍列,结构:element,string path-problem,必须包含四列,结构:element, source, sink, string,后续查询必须以element,string结构 metric @id 定义该查询的唯一标识,应以语言为开头,支持的语言如下: C and C++: cpp C#: cs Go: go Java: java JavaScript and TypeScript: js Python: py 后面建议接上一个该查询所针对的问题,比如 @id cs/command-line-injection @id java/string-concatenation-in-loop */
控制流写法
/** * @id problem * @name problem * @description problem * @kind problem * @problem.severity warning */ import java import semmle.code.java.dataflow.DataFlow import semmle.code.java.dataflow.FlowSources import semmle.code.java.dataflow.TaintTracking import UnsafeDeserialization from RemoteUserInput source, UnsafeDeserializationSink sink where source.flowsTo(sink) select source, sink
数字流污点分析写法(返回是与否),终点区别在于@kind 的定义.
** * @id problem * @name xiaomingTest * @description problem * @kind path-problem * @problem.severity warning */ import java import semmle.code.java.dataflow.FlowSources import semmle.code.java.dataflow.TaintTracking import semmle.code.java.security.QueryInjection import DataFlow::PathGraph import semmle.code.java.security.UnsafeDeserializationQuery import semmle.code.java.security.XSS import semmle.code.java.security.JndiInjectionQuery class MyConfig extends TaintTracking::Configuration { MyConfig() { this = "不重要的名字" } override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource or exists(MethodAccess call | call.getMethod().getName()="getCookies" and src.asExpr()=call ) } override predicate isSink(DataFlow::Node sink) { exists(MethodAccess call | ( call.getMethod().getName()="readObject" or call.getMethod().getName()="startsWith" or call.getMethod().getName()="indexOf" or call.getMethod().getName()="split" or call.getMethod().getName()="endsWith" or call.getMethod().getName()="contains" ) and ( sink.asExpr()=call or sink.asExpr()=call.getAnArgument() ) ) } override predicate isSanitizer(DataFlow::Node node) { super.isSanitizer(node) or node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType or node.getLocation().toString().regexpMatch(".*src/test/.*") } } from MyConfig config, DataFlow::PathNode source, DataFlow::PathNode sink where config.hasFlowPath(source, sink) select source.getNode(), source, sink,"source"
类似于白名单机制:isSanitizer是CodeQL的类TaintTracking::Configuration提供的净化方法。它的函数原型是:
override predicate isSanitizer(DataFlow::Node node) {}
在CodeQL自带的默认规则里,对当前节点是否为基础类型做了判断。
override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node)
or node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
or node.getLocation().toString().regexpMatch(".*src/test/.*")
}
表示如果当前节点是上面提到的基础类型,那么此污染链将被净化阻断,漏洞将不存在。
漏报数据链接:isAdditionalTaintStep方法是CodeQL的类TaintTracking::Configuration提供的的方法,它的原型是:
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {}
//列子
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
isTaintedString(node1.asExpr(), node2.asExpr())
}
它的作用是将一个可控节点A强制传递给另外一个节点B,那么节点B也就成了可控节点。
我们介绍了使用CodeQL表示语法时最常用的标准类:Module、Class、 Function、Stmt以及 Expr类,它们都是AstNode的子类 AstNode Module -- python模块 Class -- 类 Function -- 函数 Stmt -- 语句 Assert -- assert语句 Assign AssignStmt -- 赋值语句 x=y ClassDef -- 类定义语句 FunctionDef -- 函数定义语句 AugAssign -- 自增赋值语句 x+=y Break -- break语句 Continue -- continue语句 Delete -- del语句 ExceptStmt -- try语句中的except部分 Exec -- exec语句 For -- for语句 If -- if语句 Pass -- pass语句 Print -- print语句 Raise -- raise语句 Return -- return语句 Try -- try语句 While -- while语句 With -- with语句 Expr -- 表达式 Attribute -- 类属性 obj.attr Call -- 函数调用 f(arg) IfExp -- 条件表达式 x if cond else y Lambada -- lambda表达式 Yield -- yield表达式 Bytes -- 字节文字,b"x"或(在python2中)的"x" Unicode -- Unicode文字,u"x"或(在python3中)的"x" Num -- 数字文字 3或者4.2这种 IntegerLiteral 整型 FloatLiteral 浮点型 ImaginaryLiteral (这是啥类型) Dict -- 字典,{'a':2} Set -- 集合,{'a','b'} List -- 列表,['a','b'] Tuple -- 元组,('a','b') DictComp -- 字典推导式,{k:v for ...} SetComp -- 集合推导式,{x for ...} ListComp -- 列表推导式,[x for ...] GenExpr -- 生成器表达式,(x for ...) Subscript -- 下标操作,seq[index] Name -- 对变量的引用,var UnaryExpr -- 一元运算,-x BinaryExpr -- 二元运算,x+y Compare -- 比较操作,0<x<10 BoolExpr -- 短路逻辑运算,x and y,x or y 变量 Variables Variable -- 变量 LocalVariable -- 函数或者类的局部变量 GlobalVariable -- 全局(模块级)变量 其他 Comment -- 注释
https://www.freebuf.com/articles/web/283795.html (java Lombok问题
) 有些问题写的比较好,可借鉴参考
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。