这玩意比较抽象,全靠自己理解。推荐两个入门文章
codeQL入门,CodeQL从入门到放弃
网上文章也开始多起来了,学吧
好文推荐
- codeQL入门
- CodeQL从入门到放弃
- S2-057漏洞原作者自述:如何利用自动化工具发现5个RCE
- 代码分析平台CodeQL学习手记
- 使用codeql挖掘fastjson利用链
-
一些奇妙的方法
method.getEnclosingStmt()
:可以获取该表达式所属的最内层语句- 谓词
ASTNode.getAChild()
:返回本AST节点的所有子节点 Callable
是被调用的函数,而Call
则是调用Callable
:https://www.cnblogs.com/goodhacker/p/14752396.html
练习
micro_service_seclab
上面的CodeQL从入门到放弃带我们入土了sql的检测,我这里练习rce的检测RCE.ql
2022.01.13-update:适应了java-sec-code,但是匹配不上下面的,后面再搞
@GetMapping("/vuln/yarm")
public void yarm(String content) {
Yaml y = new Yaml();
y.load(content);
}
/**
* @id java/examples/vuldemo
* @name RCEConfig
* @description RCEConfig
* @kind path-problem
* @problem.severity warning
*/
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.QueryInjection
import DataFlow::PathGraph
class VulConfig extends TaintTracking::Configuration {
VulConfig() { this = "RCEConfig" }
override predicate isSource(DataFlow::Node src) {
src instanceof RemoteFlowSource
}
override predicate isSink(DataFlow::Node sink) {
exists(Method method, Call call |
// 用这个名字的可能不是什么好东西,这个exec我是将他也作为了Runtime去扫,所以下面就不再有这个类
method.hasName("exec")
or method.hasName("eval")
or method.hasName("evaluate") |
call.getCallee() = method
and sink.asExpr() = call.getArgument(0)
)
or
exists(ConstructorCall expr, Constructor cons |
// 还有这个
cons.getDeclaringType().hasQualifiedName("java.lang", "ProcessBuilder") |
expr.getConstructor() = cons
and sink.asExpr() = expr.getArgument(0)
)
}
}
from VulConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select source.getNode(), source, sink, "source"
SSRF.ql
虽然不能说有newURL(url)
就算ssrf,但是这样误报总比漏报好,newURL(url)
一般都会用到,先就这样
/**
* @id java/examples/vuldemo
* @name RCEConfig
* @description RCEConfig
* @kind path-problem
* @problem.severity warning
*/
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.QueryInjection
import DataFlow::PathGraph
class VulConfig extends TaintTracking::Configuration {
VulConfig() { this = "SSRFConfig" }
override predicate isSource(DataFlow::Node src) {
src instanceof RemoteFlowSource
}
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall expr, Constructor cons |
expr.getConstructor() = cons
and cons.getDeclaringType().hasQualifiedName("java.net", "URL")
and sink.asExpr() = expr.getArgument(0)
)
}
}
from VulConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select source.getNode(), source, sink, "source"