
दूरस्थ कोड निष्पादन DbGate में functionName इंजेक्शन के माध्यम से loadReader एंडपॉइंट में — CVSS 8.8
functionName इंजेक्शन के माध्यम से रिमोट कोड निष्पादनगंभीरता: उच्च (CVSS 8.8)
CWE: CWE-94 — कोड के जनरेशन का अनुचित नियंत्रण ('कोड इंजेक्शन')
प्रभावित: dbgate-api ≤ 7.1.8 (7.1.9 में पैच किया गया)
सलाह: GHSA-hv83-ggc4-v385
NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-48017
क्रेडिट: Romain Deperne
POST /runners/load-reader एंडपॉइंट एक functionName पैरामीटर लेता है और इसे सीधे एक JavaScript टेम्पलेट स्ट्रिंग में इंटरपोलेट करता है जिसे फिर एक फोर्क किए गए प्रक्रिया में निष्पादित किया जाता है — बिना किसी सैनिटाइजेशन या वैलिडेशन के। कोई भी प्रमाणित उपयोगकर्ता (बिना किसी विशेष अनुमति के) इच्छित कॉल से बाहर निकल सकता है और मनमाना JavaScript चला सकता है, जिससे सर्वर पर रिमोट कोड निष्पादन प्राप्त होता है।
फोर्क किया गया रनर require = null को एक सैंडबॉक्स के रूप में सेट करता है, लेकिन इसे आसानी से दरकिनार किया जा सकता है:
process.binding("spawn_sync") अभी भी पहुँच योग्य है और एक वास्तविक OS प्रक्रिया को जन्म देता है।
मैं गार्डेड और अनगार्डेड कोड-एक्जीक्यूशन पथों के बीच अंतर के लिए DbGate के रनर सबसिस्टम का ऑडिट कर रहा था। runners.js:292 पर start() रनर ठीक से गेट किया गया है — यह testStandardPermission('run-shell-script') को कॉल करता है और platformInfo.allowShellScripting की जाँच करता है।
loadReader() वैचारिक रूप से समान कार्य करता है (यह एक JS लोडर स्क्रिप्ट बनाता है और चलाता है) लेकिन इसमें उनमें से कोई भी जाँच नहीं है। मैंने डेटा प्रवाह का पता लगाया:
runners.js:353 loadReader({ functionName, props })
runners.js:366 loaderScriptTemplate(prefix, functionName, ...)
runners.js:64 `... ${compileShellApiFunctionName(functionName)}(${JSON.stringify(props)});`
packageTools.ts:33 return `dbgateApi.${functionName}` // ← कोई सैनिटाइजेशन नहीं
functionName हमलावर-नियंत्रित है और एक निष्पादित टेम्पलेट स्ट्रिंग के अंदर पहुँचता है। dbgateApi. उपसर्ग इसके सामने एकमात्र चीज है, और यह बच योग्य है: toString(); के साथ अभिव्यक्ति को बंद करना, पेलोड इंजेक्ट करना, और // के साथ अनुगामी (${props}) पर टिप्पणी करना वैध JS उत्पन्न करता है।
फ़ाइल: packages/api/src/controllers/runners.js (loadReader → loaderScriptTemplate)
फ़ाइल: packages/tools/src/packageTools.ts:33 (compileShellApiFunctionName)
// packageTools.ts:33 — functionName बिना सैनिटाइजेशन के प्रवाहित होता है
return `dbgateApi.${functionName}`;
// runners.js:64 — निष्पादित लोडर टेम्पलेट में इंटरपोलेट किया गया
`const reader = await ${compileShellApiFunctionName(functionName)}(${JSON.stringify(props)});`
उत्पन्न (इंजेक्टेड) स्क्रिप्ट:
const reader = await dbgateApi.toString();
process.binding("spawn_sync").spawn({ file:"/bin/sh", args:["/bin/sh","-c","id"], ... });
dbgateApi.toString//({});
compileShellApiFunctionName() एक छोटे नाम को पूर्ण-योग्य API पथ (dbgateApi.<name>) में बदलने के लिए लिखा गया था, जो functionName को एक पहचानकर्ता मानते हुए विश्वास करता था। मान, हालांकि, सीधे HTTP अनुरोध निकाय से आता है। क्योंकि इसे स्रोत में संयोजित किया जाता है जिसे बाद में eval/फोर्क किया जाता है, विश्वास धारणा एक RCE है। require = null सैंडबॉक्स मदद नहीं करता — Node का आंतरिक process.binding("spawn_sync") इसे बायपास करता है।
फिक्स (7.1.9): लोडर स्क्रिप्ट में संकलित करने से पहले functionName को एक सख्त पहचानकर्ता अनुमति-सूची के विरुद्ध मान्य करें।
poc/rce_loadreader_functionname_injection.py — वास्तविक एंडपॉइंट को एंड-टू-एंड चलाता है।
# मौजूदा JWT के साथ
python3 poc/rce_loadreader_functionname_injection.py http://localhost:3000 <JWT> 'id > /tmp/pwned'
# या पहले लॉगिन करें
python3 poc/rce_loadreader_functionname_injection.py http://localhost:3000 --login admin password 'id'
स्क्रिप्ट functionName पेलोड बनाती है, इसे POST /runners/load-reader पर भेजती है, और इंजेक्टेड spawn_sync कॉल फोर्क किए गए रनर प्रक्रिया में कमांड को निष्पादित करता है।
DbGate API होस्ट पर प्रमाणित RCE। DbGate एक डेटाबेस प्रबंधन GUI है जो अक्सर आंतरिक डेटाबेस तक व्यापक नेटवर्क पहुँच के साथ तैनात किया जाता है — इस पर कोड निष्पादन डेटा टियर में एक मजबूत पिवट है।
जिम्मेदारी से प्रकटीकरण। फिक्स शिप होने के बाद PoC प्रकाशित किया गया, डिफेंडर्स और डिटेक्शन इंजीनियरिंग के लिए।