
n8n 2.42.0 샌드박스 이스케이프에 대한 개념 증명 및 실습 환경: 숨겨진 Function/FunctionItem 노드가 메인 프로세스에서 JS를 실행하여 인증된 멤버에게 호스트 RCE를 부여합니다.
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · n8n-function-vm2
n8n 2.42.0 - n8n GmbH
GHSA-j4p8-h8mh-rh8q는 **n8n-nodes-base.code**를 JS task-runner 자식 프로세스로 옮겼다. 프로덕션 스폰은 --disallow-code-generation-from-strings와 --disable-proto=delete를 추가한다. 남은 것은 옮기는 대신 숨겨둔 노드들이다. Function.node.ts는 hidden: true다. FunctionItem도 그렇다. LangChain Code도 그렇다. 팔레트 숨김은 UI 플래그일 뿐이다. 워크플로 JSON 저장/가져오기는 여전히 해당 타입을 해석한다. 기본 NODES_EXCLUDE는 Execute Command와 Local File Trigger뿐이다. 실행 경로는 n8n 메인 프로세스 내의 인프로세스 vm2 NodeVM 3.12.2다.
워크플로를 생성할 수 있는 기본 멤버가 n8n 메인 프로세스에서 JS를 실행할 수 있다. 숨김은 ACL이 아니다.
| ID | 아직 CVE 없음 |
| CWE | CWE-94, CWE-269 |
| CVSS | High: 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| 제품 | n8n |
| 영향받는 버전 | 2.42.0(86c23326)까지; GHSA-j4p8의 잔여물 |
| 인증 | 워크플로 생성/가져오기/실행 권한이 있는 인증된 멤버 |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1 전용 |
기본 멤버로서 노드 type이 n8n-nodes-base.function(또는 functionItem, 또는 @n8n/n8n-nodes-langchain.code)인 워크플로를 가져오거나 생성하고 실행하면 된다. JS는 n8n 메인 프로세스에서 실행된다.
이는 n8n UID 권한으로의 호스트 RCE다: 인스턴스 시크릿, 디스크에 있는 다른 사용자의 자격 증명 암호문, DB. 멀티테넌트 멤버에서 인스턴스 탈취로 이어진다. OS LPE가 아니다. 인증되지 않은 공격도 아니다. 같은 인스턴스의 Code v2는 그런 식으로 process를 보지 못한다.
같은 제품, 형제 잔여물: Databricks path join.
먼저 2026년 9월 16일 GHSA 물결을 읽고, 태그 [email protected]에서 열 번의 헌트를 진행했다. 표현식 샌드박스, Code/Function/vm2, 자격 증명, 웹훅, HTTP/SSRF, Git 노드, 커뮤니티 패키지, 인증/SSO, 노드 주입, 퍼블릭 API. 그 물결의 대부분의 High는 이 핀에서 닫혀 있다. Code는 끝나지 않았다.
v3 브레이킹 체인지 규칙은 이미 Function / FunctionItem을 제거됨으로 표시한다. 2.42.0에서는 이들이 잔여물이며, 의도된 장기 샌드박스가 아니다. Function은 또한 this.helpers를 주입하는데, 여기에는 JS 러너가 지원하지 않는다고 나열한 헬퍼도 포함된다. 프로세스 경계를 증명하는 데 공개된 vm2 가젯은 필요하지 않았다.
순정 n8nio/n8n:2.42.0을 띄우고, 멤버(인스턴스 소유자가 아님)로 가입하고, n8n-nodes-base.function을 가져와 실행했다. Function pid=7은 n8n 메인 PID다. Code v2의 동일한 JS: hasProcess: false. Task-runner 자식은 pid 26이다. 증인 N8N-FUNCTION-VM2-WITNESS.
이미 기록된 잘못된 방향들: Function 타입이 hidden/unknown으로 거부됨(그러면 노드가 실제로 제외됨); Function pid가 task-runner 자식과 같음(그러면 이미 옮겨진 것); Code v2가 process를 봄(그러면 러너가 컨트롤이 아님); vm2 익스플로잇 가젯, 리버스 셸, OS LPE. 연극이다. 증인은 메인 PID 대 hasProcess: false다.
cd lab
./run.sh
대상은 오직 http://127.0.0.1:18201. 기본 NODES_EXCLUDE. 공격자는 멤버다.
authenticated-as=member
function-fields pid=7 witness=N8N-FUNCTION-VM2-WITNESS
code-fields hasProcess=False pid=None
compare function_pid=7 code_pid=None main_pid=7 runner_pid=26 who=member
SUCCESS N8N-FUNCTION-VM2 who=member function_pid=7 code_pid=None main_pid=7 runner_pid=26 N8N-FUNCTION-VM2-WITNESS
기본 NODES_EXCLUDE에 n8n-nodes-base.function, n8n-nodes-base.functionItem, @n8n/n8n-nodes-langchain.code를 추가하거나, Code v2가 이미 하는 방식대로 JsTaskRunnerSandbox를 통해 라우팅하라. 팔레트 hidden으로는 충분하지 않다.
Function.node.ts · Code.node.ts · nodes.config.ts · task-runner-process-js.tsGNU Affero GPL v3.0. LICENSE 참조. 루프백 랩 전용. 보증 없음.