CodeQL小记
CodeQL小记
前言
这个文章是用来记录学习CodeQL过程中遇到的问题和一些常用的东西
创建数据库
按照自己的理解,codeql创建java类的数据库是通过编译过程
中获取AST
开源
对于有开源的系统直接使用官方的就行
codeql database create <database> --language=<language-identifier>
指定build命令
codeql database create java-database --language=java --command="mvn clean install"
闭源
对于闭源项目,首先考虑是否存在已知数据库,然后再自己构建
构建闭源项目的数据库,直接使用Gitbub上的开源项目,有时候需要自己修改一些东西,遇到问题解决问题
单jar/war文件
这种情况下,目前我只使用过CodeQLpy
,
python3 main.py -t xxx.jar -c
然后
codeql database create qldbname --language=java --command="run.cmd" --overwrite
如果报错了可能是因为依赖的问题,自己根据依赖适当修改
多jar文件
这种情况使用的是extractor-java
这个项目
第一次使用可能会因为找不到codeql路径然后报错,修改一些代码即可
以创建weblogic的数据库为例子
首先用脚本把jar包都复制出来
import os
import shutil
# 源目录路径
source_dir = 'E:\\Oracle_Home\\wlserver'
# 目标目录路径
target_dir = 'E:\\wb'
# 确保目标目录存在,如果不存在则创建
if not os.path.exists(target_dir):
os.makedirs(target_dir)
# 递归遍历源目录下的所有文件和子目录
for root, dirs, files in os.walk(source_dir):
for file in files:
if file.endswith('.jar'):
source_path = os.path.join(root, file)
target_path = os.path.join(target_dir, file)
shutil.copy(source_path, target_path)
print(f'Copied {file} to {target_path}')
print('All .jar files have been copied to the target directory.')
然后用下面命令将源码包和依赖包分别拷贝到不同目录(这里我默认将以com.oracle.weblogic.开头的视为weblogic本身,其他jar包视为依赖):
mkdir -p weblogic/lib_/
find ./wb -type f -name "*.jar" | grep "com.oracle.weblogic."| xargs -I {} cp {} ./weblogic/
find ./wb -type f -name "*.jar" | grep -v "com.oracle.weblogic."| xargs -I {} cp {} ./weblogic/lib_
将源码包解压:
cd weblogic/
ls |grep ".jar" | xargs -I {} unzip -q -n {}
反编译class(只处理包名为weblogic.application的类):
python3 ~/extractor-java/class2java.py xxx/weblogic/application/
然后就是编译CodeQL数据库:
python3 ~/extractor-java/run.py weblogic_qldb xxx/weblogic/application/ -ld weblogic/lib_/
CodeQL项目创建
新建一个文件夹,例如test
然后在test文件夹下创建一个文件qlpack.yml,注意:名字必须为qlpack.yml
内容如下:
name: xxx
version: 0.0.0
libraryPathDependencies: codeql-java
官方:编辑 name
属性,使其与格式 <scope>/<name>
匹配,其中 <scope>
是要发布到的 GitHub 组织或用户帐户的名称
说实话,日常使用name
我是随便写的
全局污点分析
想要能够看到每个节点的位置就要按照格式写
参考下面代码格式
/**
* @kind path-problem
*/
import java
import DataFlow2::PathGraph
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking2
class MyTaintTrackingConfiguration extends TaintTracking2::Configuration {
MyTaintTrackingConfiguration() {
this = "MyTaintTrackingConfiguration"
}
override predicate isSource(DataFlow::Node source) {
......
}
override predicate isSink(DataFlow::Node sink) {
......
}
}
from MyTaintTrackingConfiguration config, DataFlow2::PathNode source,DataFlow2::PathNode sink
where config.hasFlowPath(source, sink)
select source.getNode(), source, sink, "fastJsonInject!"
主要是开头的@kind path-problem
、import
的内容、
结果输出格式:
from MyTaintTrackingConfiguration config, DataFlow2::PathNode source,DataFlow2::PathNode sink
where config.hasFlowPath(source, sink)
select source.getNode(), source, sink, "xxxxx"
QL收集
JNDI注入:
/**
* @kind path-problem
*/
import java
import DataFlow2::PathGraph
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking2
class Context extends RefType{
Context(){
this.hasQualifiedName("javax.naming", "Context")
or
this.hasQualifiedName("javax.naming", "InitialContext")
or
this.hasQualifiedName("org.springframework.jndi", "JndiCallback")
or
this.hasQualifiedName("org.springframework.jndi", "JndiTemplate")
or
this.hasQualifiedName("org.springframework.jndi", "JndiLocatorDelegate")
or
this.hasQualifiedName("org.apache.shiro.jndi", "JndiCallback")
or
this.getQualifiedName().matches("%JndiCallback")
or
this.getQualifiedName().matches("%JndiLocatorDelegate")
or
this.getQualifiedName().matches("%JndiTemplate")
}
}
predicate isLookup(Expr arg) {
exists(MethodAccess ma |
ma.getMethod().getName() = "lookup"
and
ma.getMethod().getDeclaringType() instanceof Context
and
arg = ma.getArgument(0)
)
}
class MyTaintTrackingConfiguration extends TaintTracking2::Configuration {
MyTaintTrackingConfiguration() {
this = "MyTaintTrackingConfiguration"
}
override predicate isSource(DataFlow::Node source) {
source instanceof RemoteFlowSource
}
override predicate isSink(DataFlow::Node sink) {
exists(Expr arg |
isLookup(arg)
and
sink.asExpr() = arg
)
}
}
from MyTaintTrackingConfiguration config, DataFlow2::PathNode source,DataFlow2::PathNode sink
where config.hasFlowPath(source, sink)
select source.getNode(), source, sink, "JNDI!"
MyBatis框架SQL注入
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Tree's Blog!