0x00 前言
今年年初浅蓝师傅发了两篇探索高版本 JDK 下 JNDI 漏洞利用方法的文章,拜读之后一直没时间自己进行探索,正巧最近在工作期间学习codeql相关姿势,看了一下关于寻找高版本JDK下RMI可利用的类及方法的条件,很适合使用codeql写规则探索,于是在这里记录一下自己的探索过程。
写在前面,m1yuu技术有限,文中有些出错的地方或者未表达清晰的细节还请各位大佬斧正
0x01 构建codeql
本文聚焦于利用BeanFactory#getObjectInstance
扩大攻击面之后的利用方式探索。我们稍微回忆一下需要寻找的类/方法需要满足的条件,方便构造codeql语句进行查询:
对类的限制
我们寻找的类需要满足:
- 该类存在定义好的构造方法(Constructor)
- 该构造方法为public
- 该构造方法无参
m1yuu特意把构造方法Constructor用英文标出
codeql的使用规则和书写方式总结虽然官方给的很齐全,但是国内中文相关的文档还是不完善,如果想了解关于某些元素的codeql方法或者使用方式可以去官方library查询:https://codeql.github.com/codeql-standard-libraries/search.html,这里关于Constructor的使用,m1yuu去查询到了
getAConstructor()
构造UsableClass
:
class UsableClass extends RefType {
UsableClass() {
this.getAConstructor().hasNoParameters()
and this.getAConstructor().isPublic()
}
}
对方法的限制
我们寻找的方法需要满足:
- 声明为public
- 只有一个参数
- 此参数为String类型
- 该方法存在于上文提到的类中
构造UsableMethod
:
class UsableMethod extends Method {
UsableMethod() {
this.getNumberOfParameters() = 1
and this.getAParamType().hasName("String")
and this.isPublic()
}
}
尝试运行codeql
import java
class UsableClass extends RefType {
UsableClass() {
this.getAConstructor().hasNoParameters()
and this.getAConstructor().isPublic()
}
}
class UsableMethod extends Method {
UsableMethod() {
this.getNumberOfParameters() = 1
and this.getAParamType().hasName("String")
and this.isPublic()
}
}
from UsableMethod me, UsableClass cla
where
me.getDeclaringType() = cla
select cla,me
去lgtm拖了groovy的codeql数据库(https://lgtm.com/projects/g/apache/groovy/ci/),本地导入vscode之后运行上述codeql脚本,结果确实没有问题,搜索到的类和方法均满足预期条件。但是有一个细节可以缩小结果集合,在查找到的结果中有一部分是抽象类和抽象方法,这些需要从结果中删去,于是修改脚本:
import java
class UsableClass extends RefType {
UsableClass() {
this.getAConstructor().hasNoParameters()
and this.getAConstructor().isPublic()
and not this.isAbstract()
}
}
class UsableMethod extends Method {
UsableMethod() {
this.getNumberOfParameters() = 1
and this.getAParamType().hasName("String")
and this.isPublic()
and not this.isAbstract()
}
}
from UsableMethod me, UsableClass cla
where
me.getDeclaringType() = cla
select cla.getPackage(),cla,me
在select中�