定时任务功能点绕过黑白名单执行任意sql语句
字数 1232 2025-08-27 12:33:23
若依后台管理系统定时任务功能SQL注入漏洞分析
环境说明
- 目标系统:RuoYi-fast v4.7.3(前后端不分离版本)
- 漏洞组件:Quartz定时任务组件
Quartz组件基础
RuoYi-fast使用Quartz作为定时任务组件,基本使用方式如下:
- 依赖配置:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
</dependencies>
- Job实现:
public class DateTimeJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) {
String msg = (String) context.getJobDetail().getJobDataMap().get("msg");
System.out.println("current time :"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "---" + msg);
}
}
- 配置Job和Trigger:
@Configuration
public class QuartzConfig {
@Bean
public JobDetail printTimeJobDetail(){
return JobBuilder.newJob(DateTimeJob.class)
.withIdentity("DateTimeJob")
.usingJobData("msg", "Hello Quartz")
.storeDurably()
.build();
}
@Bean
public Trigger printTimeJobTrigger() {
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/1 * * * * ?");
return TriggerBuilder.newTrigger()
.forJob(printTimeJobDetail())
.withIdentity("quartzTaskService")
.withSchedule(cronScheduleBuilder)
.build();
}
}
漏洞分析
定时任务执行逻辑
-
执行流程:
AbstractQuartzJob抽象类实现了模版方法设计模式- 包含
before、doExecute、after方法 execute方法组合上述三个方法
-
关键执行点:
- 通过反射调用目标方法
- 支持两种调用方式:
- Spring容器中注册的bean
- 指定class名称(需有无参构造函数)
-
方法调用限制:
- 方法不能是private修饰
- 参数类型仅支持:String、Boolean、Long、Double、Integer
定时任务添加/修改逻辑
-
黑白名单检查:
- 添加定时任务前会检查黑白名单
- 但存在检测遗漏:仅对全限定类名(class)检测,未对Spring容器中的对象检测
-
漏洞产生原因:
- 可以绕过黑名单检测
- 可以逃过白名单检测
寻找可利用对象
在Spring容器中寻找满足以下条件的对象:
- 存在于Spring容器中
- 方法至少不是private修饰
- 参数类型为String、Boolean、Long、Double、Integer
发现可利用对象:
JdbcTemplate类中的execute和update方法- 都是public方法
- 参数为String类型
- 可以执行任意SQL语句
绕过方法参数截取
-
问题:
- 方法参数值是从目标字符串第一个
(和第一个)中间的字符串获取 - 如
jdbcTemplate.execute("insert into sys_user_role values(7,7);"),实际获取的是"insert into sys_user_role values(7,7"
- 方法参数值是从目标字符串第一个
-
绕过方案:
- 使用MySQL预处理和hex编码
- 确保参数值内容中不出现
)
-
示例攻击流程:
- 将SQL语句hex编码:
insert into sys_user_role values(7,7);→0x696E7365727420494E544F207379735F757365725F726F6C652076616C75657328372C293B - 构造无
)的payload:set @a=0x696E7365727420494E544F207379735F757365725F726F6C652076616C75657328372C293B; prepare stmt from @a; execute stmt; - 通过定时任务执行上述SQL
- 将SQL语句hex编码:
漏洞修复方案
- 完善黑白名单检测机制
- 对Spring容器中的对象也进行白名单检测
- 严格限制可执行的方法和参数类型
总结
该漏洞利用Quartz定时任务组件的反射执行机制,结合Spring容器中JdbcTemplate的可执行SQL特性,通过精心构造的SQL语句绕过参数截取限制,最终实现任意SQL语句执行。修复时应全面考虑各种调用方式和参数处理场景。