README.md
Rendering markdown...
# ──────────────────────────────────────────────────────────────────────────────
# Full lab: vulnerable n8n target + PoC attacker container
#
# Quick start:
# docker compose up -d n8n-vuln # start target, wait for "Editor is now accessible"
# docker compose run --rm poc --help # show attacker options
#
# Step-by-step exploit demo (see README.md for full walkthrough):
# 1. Open http://localhost:5678 and complete the setup wizard
# 2. Import workflow.json (or build a Chat trigger workflow manually)
# 3. Activate the workflow and trigger an execution → note the execution ID
# 4. docker compose run --rm poc \
# --target http://n8n-vuln:5678 \
# --exec-id <ID> --inject "PWNED"
# ──────────────────────────────────────────────────────────────────────────────
services:
# ── Vulnerable target ──────────────────────────────────────────────────────
n8n-vuln:
image: n8nio/n8n:1.123.22 # last affected release
container_name: n8n-vuln
restart: unless-stopped
ports:
- "5678:5678"
environment:
# Disable authentication so the public Chat trigger is reachable
# without any credentials (mirrors a misconfigured production instance)
N8N_USER_MANAGEMENT_DISABLED: "true"
N8N_BASIC_AUTH_ACTIVE: "false"
# Allow the Chat WebSocket from any origin
N8N_CORS_ORIGIN: "*"
# Persist executions in SQLite (stored in the named volume)
DB_TYPE: sqlite
DB_SQLITE_DATABASE: /home/node/.n8n/database.sqlite
# Keep executions so we can look up IDs
EXECUTIONS_DATA_SAVE_ON_SUCCESS: all
EXECUTIONS_DATA_SAVE_ON_ERROR: all
EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS: "true"
# Show full execution data (useful for research)
N8N_LOG_LEVEL: info
volumes:
- n8n_data:/home/node/.n8n
networks:
- lab
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:5678/healthz"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
# ── Attacker / PoC tool ────────────────────────────────────────────────────
poc:
build:
context: .
dockerfile: Dockerfile
image: n8n-chat-hijack-poc:latest
container_name: n8n-poc-attacker
depends_on:
n8n-vuln:
condition: service_healthy
networks:
- lab
# Default: scan execution IDs 1-200 with the standard injection payload.
# Override via: docker compose run --rm poc --exec-id 42 --inject "custom"
command:
- --target
- http://n8n-vuln:5678
- --start-id
- "1"
- --end-id
- "200"
volumes:
n8n_data:
networks:
lab:
name: ghsa-f77h-j2v7-g6mw_lab