
إعادة إنتاج حميدة ومكتفية ذاتيًا لـ CVE-2026-77521 (تنفيذ أوامر قابل لحقن المطالبات في MaxKB)
مختبر مكتفٍ ذاتيًا وغير ضار يعيد إنتاج
GHSA-f36j-f34j-h3rx
/ CVE-2026-77521: في MaxKB (منصة
مساعد ذكاء اصطناعي مؤسسي / RAG مفتوحة المصدر)، أي مساعد مزوّد بأداة،
أو أداة MCP، أو مهارة، أو تطبيق فرعي يحصل على أداة execute صدفية تُحقن تلقائيًا
وهي غير محمية ببوابة موافقة بشرية — لذا يصل حقن الأوامر (من الدردشة
أو من مستند مُستوعَب) إلى الصدفة. كان من المفترض أن يحتويه صندوق رمل (sandbox)،
لكن سلسلة نصية بـ shell=True سمحت للرموز الخاصة (metacharacters) بالإفلات منه.
| التنبيه الأمني | GHSA-f36j-f34j-h3rx |
| CVE | CVE-2026-77521 |
| المشروع | 1Panel-dev/MaxKB |
| المتأثر | < 2.10.5-lts |
| المُصلَّح | 2.10.5-lts (commit 594f50f) — جزئي، انظر أدناه |
| CVSS | 10.0 حرج (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H) |
| الضعف | CWE-78 (حقن أوامر نظام التشغيل) · CWE-250 (امتيازات غير ضرورية) · CWE-749 (طريقة خطرة مكشوفة) |
يعيد هذا إنتاج ثغرة مُصلَّحة ومُفصح عنها علنًا لأغراض تعليمية ودفاعية. يعمل محليًا بالكامل وبشكل غير ضار:
id، وكتابة ملف علامة
يحذفه إثبات المفهوم). لا يوجد gosu/صندوق رمل/جذر حقيقي — إذ يُستبدل
غلاف إسقاط الامتيازات بعلامة env خاملة حتى يعمل العرض التوضيحي في أي مكان.يُبنى مساعد MaxKB المزوّد بأي قدرة على deepagents مع
SandboxShellBackend. يحقن deepagents تلقائيًا أداة execute صدفية (إضافةً إلى
read_file/write_file/…)، ولا يستخدم MaxKB أي excluded_tools، لذا تكون execute
حاضرة دائمًا. إعداد interrupt_on — الذي يحدد ما يحتاج إلى موافقة
بشرية — هو {"write_file": False, "read_file": False, "edit_file": False}:
execute ليست فيه، لذا تعمل دون أي موافقة. أي نص يمكنه توجيه
النموذج (رسالة دردشة، أو مستند مسموم تستوعبه خط أنابيب RAG) يمكنه
بالتالي جعل الوكيل ينفذ أوامر صدفية. في عمليات التثبيت من المصدر يكون SANDBOX
معطّلًا افتراضيًا، لذا تعمل الأوامر باسم مستخدم التطبيق؛ وفي الحاوية الرسمية (الجذر)
كان غلاف صندوق الرمل سلسلة نصية بـ shell=True، لذا نُفِّذت ;/>/$() خارج
gosu، بصلاحيات الجذر.
interrupt_on الحقيقية في MaxKB،
يعمل استدعاء execute المحقون دون موافقة؛ وإضافة
"execute": True تُقيّده ببوابة. → poc/01_missing_hitl_gate.py;+إعادة توجيه من
بادئة gosu ذات السلسلة الواحدة؛ بينما تعادل إعادة الاقتباس في _build_sandbox_command()
في 2.10.5-lts ذلك. → poc/02_sandbox_escape.pyexecute بأمر المهاجم (ولا يفعل ذلك مع مستند
نظيف). → poc/03_real_llm.pyتُقوّي رقعة 2.10.5-lts المُصدَرة (commit 594f50f)
الهروب من الـ sandbox فقط — فهي تضيف _build_sandbox_command()، التي
تُقسّم على معاملات الـ shell، وتُعيد اقتباس كل token باستخدام shlex.quote، وتُغلّف
كل أمر بسيط ببادئة gosu. وبالتحقق مقابل
مصدر v2.10.5-lts،
فإن جوهر الوكالة دون تغيير: لا يزال interrupt_on يُغفل execute، ولا يزال
الـ backend هو SandboxShellBackend، ولا يزال SANDBOX افتراضيًا 0. لذا
بعد الإصلاح، لا يزال execute المُحقَن عبر prompt يعمل دون موافقة بشرية —
فقد تم تعزيز الجدار الداخلي بينما بقي البوابة مفتوحة. يُوضّح PoC 1
التخفيف المُوصى به (تقييد execute)، الذي لم يُصدِره المورّد.
لا توجد تبعيات لـ PoC 1/2 (Python 3.9+):
./run.sh # all three (PoC 3 skips without an endpoint)
python3 poc/01_missing_hitl_gate.py # missing approval gate
python3 poc/02_sandbox_escape.py # metacharacter sandbox escape
هل تعرض هذا؟ يُعدّ
DEMO.mdدليل تشغيل، ويقودهdemo.shضغطة مفتاح واحدة في كل مرة.
أي نقطة نهاية متوافقة مع OpenAI (مستضافة ذاتيًا أو نموذج مفتوح مستضاف). مثال (Groq):
export OPENAI_BASE_URL=https://api.groq.com/openai/v1
export OPENAI_API_KEY=$GROQ_API_KEY # read from env only; never logged
MODEL="openai/gpt-oss-20b" python3 poc/03_real_llm.py
خلف وكيل فحص TLS يعيد المحاولة دون التحقق مع تحذير
(INSECURE_SSL=1 لإجباره على ذلك). يتخطى بسلاسة إذا لم يتم تعيين نقطة نهاية.
| المسار | ما هو |
|---|---|
sandbox_shell.py | نموذج غير ضار لبناء أمر execute() في MaxKB — السلسلة القابلة للاستغلال مقابل _build_sandbox_command() المُصحّحة |
agent_sim.py | نموذج مصغّر لبوابة الموافقة البشرية interrupt_on في deepagents |
payloads/poisoned-document.md | مستند قاعدة معرفة مسموم من المهاجم (حقن غير مباشر) |
poc/01_missing_hitl_gate.py | تنفيذ execute المحقون يعمل دون موافقة؛ والبوابة تمنعه |
poc/02_sandbox_escape.py | الأحرف الخاصة تتجاوز بادئة gosu؛ ومحلل الإصدار 2.10.5 يحتويها |
poc/03_real_llm.py | نموذج حقيقي يستدعي execute من المستند المسموم (نظيف مقابل مسموم) |
DEMO.md / demo.sh | دليل تشغيل العارض ومشغّل العرض المتدرّج |
assets/attack-flow.{svg,png} | مخطط تدفق الهجوم (صورة المدونة الرئيسية) |
assets/poc3-groq-sample.txt | مخرجات PoC 3 المسجّلة (بديل العرض) |