
CVE-2026-39816 के लिए POC जो NiFi उपयोगकर्ताओं को बिना कोड निष्पादन अनुमतियों के मनमानी स्क्रिप्ट चलाने की अनुमति देता है
CVE-2026-39816 के लिए प्रूफ-ऑफ-कॉन्सेप्ट प्रदर्शन, Apache NiFi 2.8.0 में एक EXECUTE_CODE
अनुमति बाईपास जो एक फ्लो डिज़ाइनर को, जिसे जानबूझकर कोड-निष्पादन विशेषाधिकारों से वंचित
किया गया है, ग्राफ बंडल के ExecuteGraphQuery प्रोसेसर के माध्यम से NiFi JVM में मनमाना Groovy
चलाने की अनुमति देता है।
@Restricted एनोटेशन (CVE-2026-39816, CWE-95)NiFi कोड-निष्पादन प्रोसेसर को @Restricted(requiredPermission = RequiredPermission.EXECUTE_CODE)
एनोटेशन के माध्यम से EXECUTE_CODE अनुमति के पीछे गेट करता है। NiFi में सभी 16 समर्पित स्क्रिप्टिंग घटक —
ExecuteScript, InvokeScriptedProcessor, ExecuteGroovyScript,
ScriptedTransformRecord, आदि — यह एनोटेशन रखते हैं, इसलिए एक फ्लो
डिज़ाइनर को स्पष्ट EXECUTE_CODE अनुमति दी जानी चाहिए इससे पहले
प्राधिकरण परत उन्हें इन प्रोसेसरों को बनाने या कॉन्फ़िगर करने की अनुमति देगी।
ग्राफ बंडल (nifi-graph-nar + nifi-other-graph-services-nar)
एक तीसरा कोड-निष्पादन पथ भेजता है जिसमें यह एनोटेशन लापता है:
// nifi-extension-bundles/nifi-graph-bundle/nifi-other-graph-services/
// src/main/java/org/apache/nifi/graph/TinkerpopClientService.java:451
protected Map<String, String> bytecodeSubmission(
String s, Map<String, Object> map, GraphQueryResultCallback cb) {
...
compiled = groovyShell.parse(s); // line 463 — compile attacker string
compiledCode.put(s, compiled);
...
compiled.setBinding(bindings);
Object result = compiled.run(); // line 477 — execute in NiFi JVM
s पैरामीटर ExecuteGraphQuery प्रोसेसर की "Graph Query" संपत्ति से क्वेरी स्ट्रिंग है, जो बिना बदलाव के पारित होती है। कोई सैनिटाइज़ेशन नहीं है, कोई अनुमत सूची नहीं है, और कोई सैंडबॉक्स नहीं है — कोई भी मान्य Groovy NiFi प्रक्रिया के पूर्ण विशेषाधिकारों के साथ संकलित और निष्पादित किया जाता है।
न तो TinkerpopClientService और न ही ExecuteGraphQuery /
ExecuteGraphQueryRecord प्रोसेसर जो इसे चलाते हैं, @Restricted एनोटेशन रखते हैं। इसलिए NiFi की प्राधिकरण परत उन्हें सामान्य घटकों के रूप में मानती है, और एक फ्लो डिज़ाइनर जिसे स्पष्ट रूप से EXECUTE_CODE से वंचित किया गया है, फिर भी उन्हें बना सकता है।
एक NiFi 2.8.0 सर्वर शोषण योग्य है जब दोनों निम्नलिखित सत्य हों:
वैकल्पिक ग्राफ बंडल स्थापित है। विशेष रूप से
nifi-other-graph-services-nar NAR — यह वह बंडल है जो
TinkerpopClientService भेजता है। इस NAR के बिना सर्वर प्रभावित नहीं होते हैं।
कम से कम एक उपयोगकर्ता के पास फ्लो-डिज़ाइनर-शैली की अनुमतियाँ
(एक प्रोसेस ग्रुप और /controller पर read/write) बिना
EXECUTE_CODE के हैं। यह एक सामान्य नीति आकार है: एक संगठन
चाहता है कि उपयोगकर्ता पाइपलाइन बना और संशोधित कर सकें, लेकिन मनमाना
कोड नहीं चला सकें। EXECUTE_CODE अनुमति ठीक वही
सुरक्षा सीमा है जिसे नीति लागू करने के लिए है।
यदि दोनों शर्तें पूरी होती हैं, तो उपयोगकर्ता "ByteCode Submission" मोड में एक
TinkerpopClientService कॉन्फ़िगर कर सकता है, इसे किसी भी पहुंच योग्य
Gremlin सर्वर पर इंगित कर सकता है (Gremlin सर्वर केवल सेवा
प्रारंभिकरण के लिए उपयोग किया जाता है — निष्पादन स्थानीय रूप से होता है), और "Graph Query"
संपत्ति में Groovy कोड के साथ एक ExecuteGraphQuery प्रोसेसर बना सकता है।
प्रोसेसर शुरू करना NiFi JVM में Groovy को संकलित और चलाता है।
NiFi सेवा खाते के रूप में मनमाना कोड निष्पादन। वहाँ से:
flow.json.gz में लिखकर, ऑटोलोड निर्देशिका में एक NAR
छोड़कर, या एक कंट्रोलर सेवा को संशोधित करके स्थिरता स्थापित करें।शोषण EXECUTE_CODE अनुमति को बायपास करता है, इसलिए यह तब भी काम करता है
जब ऑपरेटर ने स्पष्ट रूप से उपयोगकर्ता से कोड-निष्पादन अधिकार हटा दिए हों —
ठीक वही परिदृश्य जिसे रोकने के लिए अनुमति मौजूद है।
यह रिपॉजिटरी एक POC भेजता है, जो सबसे सीधे ट्रिगर को कवर करता है:
हमलावर-नियंत्रित Groovy सीधे Graph Query प्रोसेसर संपत्ति में रखा गया। कोई अपस्ट्रीम कनेक्शन नहीं, कोई Expression Language नहीं, कोई FlowFile सामग्री आवश्यक नहीं — बस प्रोसेसर अपने स्वयं के टाइमर पर चल रहा है।
दो अतिरिक्त कोड पथ मौजूद हैं (FlowFile बॉडी सामग्री क्वेरी के रूप में उपयोग की जाती है जब Graph Query खाली होता है, और हमलावर-प्रभावित FlowFile विशेषताओं का Expression Language क्वेरी टेम्पलेट में प्रक्षेप)। उन्हें यहां प्रदर्शित नहीं किया गया है क्योंकि वे अतिरिक्त पूर्व शर्तों के साथ एक ही सिंक तक पहुंचते हैं; प्रत्यक्ष पथ EXECUTE_CODE बाईपास साबित करने के लिए पर्याप्त है।
setup/ — Docker Compose वातावरण। ग्राफ बंडल NARs के साथ एक NiFi 2.8.0 इंस्टेंस (आधिकारिक apache/nifi:2.8.0 छवि) ऑटोलोडेड, दो परीक्षण उपयोगकर्ताओं (admin और flow_designer) प्रदान करने वाला एक LDAP सर्वर, और TinkerpopClientService के लिए इंगित करने हेतु एक Gremlin सर्वर लाता है। setup.sh नीतियों को बूटस्ट्रैप करता है ताकि flow_designer के पास फ्लो-संपादन अधिकार हों लेकिन EXECUTE_CODE नहीं, फिर कॉन्फ़िगरेशन सत्यापित करता है।
pocs/flow_designer_groovy_rce.py — स्व-निहित शोषण। flow_designer के रूप में प्रमाणित करता है, प्रदर्शित करता है कि ExecuteScript अस्वीकृत है (EXECUTE_CODE गेट काम कर रहा है), फिर एक Groovy पेलोड के साथ एक + बनाता है जो POC द्वारा स्थानीय रूप से शुरू किए गए लिसनर के लिए एक bash रिवर्स शेल उत्पन्न करता है। एक बार कनेक्शन स्थापित होने के बाद, POC util-linux के माध्यम से शेल को पूरी तरह से इंटरैक्टिव PTY-समर्थित bash में अपग्रेड करता है, रॉ-मोड stdio ब्रिजिंग और लाइव विंडो रीसाइज़िंग के साथ — ऑपरेटर को NiFi कंटेनर के अंदर एक वास्तविक टर्मिनल मिलता है।
पूर्वापेक्षाएँ: Docker, Python 3.10+, और uv।
cd setup
./setup.sh
पहला रन Maven Central से ग्राफ-बंडल NARs डाउनलोड करता है और Docker छवियों को खींचता है (~2-3 मिनट)। जब सेटअप पूरा होता है तो यह पेस्ट-रेडी POC आह्वान प्रिंट करता है।
POC चलाएँ:
uv run --no-project --with requests \
pocs/flow_designer_groovy_rce.py \
--base-url https://localhost:8443 \
--username flow_designer \
--password 'flowDesigner123!' \
--gremlin-host gremlin-server
POC ऑपरेटर को nifi सेवा खाते के रूप में चल रहे NiFi कंटेनर के अंदर एक इंटरैक्टिव bash सत्र में छोड़ देता है। डिस्कनेक्ट करने के लिए exit टाइप करें या Ctrl-D दबाएँ — POC फिर बनाए गए प्रोसेसर और कंट्रोलर सेवा को साफ कर देगा।
Linux Docker पर (जहाँ host.docker.internal डिफ़ॉल्ट रूप से हल नहीं होता है), --shell-host <host-bridge-ip> पास करें या setup/docker-compose.yml में nifi सेवा में extra_hosts: ["host.docker.internal:host-gateway"] जोड़ें।
टियर डाउन:
cd setup
./teardown.sh
TinkerpopClientServiceExecuteGraphQueryscript