RuoYi-Flowable-Plus 0day表达式注入
字数 1676 2025-08-03 16:44:16
RuoYi-Flowable-Plus 表达式注入漏洞分析与利用指南
漏洞概述
RuoYi-Flowable-Plus是基于若依系统二次开发的工作流系统,集成了Flowable流程引擎。该系统v0.8.3版本存在表达式注入漏洞,攻击者可通过精心构造的表达式实现远程代码执行。
受影响版本
- RuoYi-Flowable-Plus v0.8.3
- 下载地址:https://gitee.com/KonBAI-Q/ruoyi-flowable-plus
漏洞利用方法
方法一:使用Java类实现RCE
条件要求:
- 目标类需要具有公共无参构造函数(系统使用newInstance实例化)
- 需要实现JavaDelegate接口,存在execute函数
可利用类:
-
org.flowable.engine.impl.test.NoOpServiceTask
- 添加name表达式:
${''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('calc.exe')}
- 添加name表达式:
-
org.flowable.engine.impl.bpmn.listener.ScriptExecutionListener
- 添加以下两个变量(选择表达式类型):
- script:
var System = java.lang.Runtime.getRuntime().exec("calc"); - language:
js
- script:
- 添加以下两个变量(选择表达式类型):
方法二:直接使用表达式
直接使用表达式注入:
${''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('calc.exe')}
详细利用步骤
利用NoOpServiceTask类
- 新建表单并保存
- 新增流程分类
- 新增流程模型
- 点击"设计"按钮
- 点击创建开始事件,并添加监听器
- 设置监听器内容为NoOpServiceTask类,并添加恶意表达式
- 选择之前新建的表单
- 保存流程
- 点击"部署"按钮
- 新建流程并点击"发起"
- 随意输入值点击"提交",命令执行成功
利用ScriptExecutionListener类
- 将流程模型中的监听器改为ScriptExecutionListener
- 设置script和language参数为恶意值
- 点击"部署"(必须步骤,否则流程模型不会被更改)
- 在新建流程中发起流程,点击提交触发漏洞
直接使用表达式
- 在适当位置插入恶意表达式
- 点击部署
- 发起流程,命令执行成功
漏洞原理分析
Java类利用流程
org.flowable.engine.impl.bpmn.listener.ListenerNotificationHelper#executeExecutionListeners开始处理- 进入
createClassDelegateExecutionListener函数,调用create函数 - 创建
ClassDelegate类并将监听器赋值到此类中 - 执行
ClassDelegate类的notify函数 - 最终执行到
defaultInstantiateDelegate函数实例化监听器 - 返回到
DelegateExecutionListener的构造函数 - 调用
DelegateExecutionListener类的notify函数 - 经过一系列函数调用后解析表达式,实现命令执行
表达式直接利用流程
org.flowable.engine.impl.bpmn.listener.ListenerNotificationHelper#executeExecutionListeners处理- 直接创建
ExpressionExecutionListener类 - 调用
ExpressionExecutionListener类的notify函数 - 最终解析表达式,实现命令执行
防御建议
- 升级到最新版本,检查是否有官方补丁
- 对用户输入的表达式进行严格过滤和验证
- 限制Flowable引擎的表达式解析能力
- 实施最小权限原则,限制系统命令执行能力
- 使用安全沙箱技术限制表达式执行环境
总结
该漏洞利用Flowable流程引擎的表达式解析功能,通过精心构造的恶意表达式实现远程代码执行。攻击者需要具备一定的后台操作权限,但一旦利用成功危害极大。建议用户及时采取防护措施,避免系统被攻击者控制。