
استشارة أمنية وإثبات مفهوم لثغرة حقن أوامر نظام التشغيل في أداة مساعدة ffmpeg لـ MCP، مع تحليل السبب الجذري وإرشادات الكشف وإجراءات التخفيف لحزمة npm غير مصححة.
تمرّر الدالة runFFmpegCommand سلسلة مبنية من معاملات أدوات MCP إلى spawn(…, { shell: true })، لذا فإن المحارف الخاصة بالقشرة (shell metacharacters) في options أو format أو codec أو pixelFormat أو extraOptions تُنفَّذ على المضيف الذي يشغّل الخادم.
⚠ لا توجد نسخة مُصحَّحة
اعتبارًا من 2026-08-22، أحدث إصدار على npm هو 0.2.1، وهو الإصدار المتأثر، وما تزال نقطة الضعف موجودة على الفرع الافتراضي للمستودع. لا يوجد إصدار للترقية إليه. انظر التخفيف لمعرفة ما يمكن للمستخدمين فعله في هذه الأثناء.
وسائط أدوات MCP تخضع لتأثير المهاجم. فهي مُنتَجة بواسطة نموذج لغوي كبير (LLM) من المحتوى الذي يعالجه الوكيل — مستندات وصفحات ويب ومخرجات أدوات — لذا فإن حقن التلقين غير المباشر (indirect prompt injection) يضع المهاجم في موضع التحكم بقيم الوسائط التي يستقبلها معالج الأداة. أي معالج يُغذّي القشرة بأيٍّ من تلك القيم يحوّل هذا التأثير إلى تنفيذ أكواد على المضيف الذي يشغّل خادم MCP. هذا هو النموذج نفسه للحالة السابقة aws-mcp-server / CVE-2026-5058.
إن خادم تحويل الوسائط هدف طبيعي بشكل خاص لهذا النوع من الهجمات: فالملفات التي يُطلب منه معالجتها هي بالضبط المحتوى غير الموثوق الذي يلتقطه الوكيل من أماكن أخرى.
src/utils/ffmpeg.ts — يُجمَّع الأمر كسلسلة نصية وتُفعَّل القشرة صراحةً:
function runProcess(command: string, args: string[], useShell = false) {
const child = spawn(command, args, { shell: useShell, windowsHide: true });
…
}
export async function runFFmpegCommand(command: string): Promise<string> {
const { stdout, stderr, code } = await runProcess(`ffmpeg ${command}`, [], true);
…
}
يُمرِّر spawn("ffmpeg " + command, [], { shell: true }) السلسلة كاملة عبر /bin/sh -c. كل ما أسهم به المتصل في command يُعامَل كصيغة قشرة.
يصل src/tools/handlers.ts إلى هذا المساعد من ثلاث أدوات، بإدراج معاملات لا يُتحقق من محتواها أبدًا:
| الأداة | المعاملات القابلة للحقن |
|---|---|
convert_video |
الوحيدان اللذان يخضعان لأي فحص هما inputPath و outputPath، ومخططات Zod تتحقق من النوع فقط (z.string())، لا من المحتوى أبدًا — لذا تمر المحارف الخاصة دون أي رقابة.
استدعاء convert_video مع ضبط options على ; touch /tmp/marker ; يُنتج:
/bin/sh -c "ffmpeg -i /tmp/in.mp4 ; touch /tmp/marker ; /tmp/out.mp4"
poc/driver.mjs يتواصل مع MCP عبر stdio: يهيّئ الخادم، ويصدر استدعاء tools/call واحدًا لـ convert_video بقيمة options محقونة، ثم يتحقق من وجود ملف علامة. الحمولة هي أمر touch غير مؤذٍ.
npm pack @sworddut/[email protected]
tar xf sworddut-mcp-ffmpeg-helper-0.2.1.tgz && cd package && npm install
node ../poc/driver.mjs
المتوقع على إصدار متأثر:
==== POC RESULT (@sworddut/mcp-ffmpeg-helper) ====
marker /tmp/PWNED_ffmpeg created: true
verdict: CONFIRMED — command injection executed
لا يلزم تثبيت ffmpeg — فالأمر المحقون يُنفَّذ ضمن نفس سلسلة /bin/sh -c بصرف النظر عمّا إذا كان من الممكن حلّ (resolve) الثنائي الأول أم لا. جرى التحقق منه بتاريخ 2026-06-01 في حاوية معزولة، وأُعيد التحقق بتاريخ 2026-06-13، وأُكِّد مجددًا وجود نقطة الضعف على الفرع الافتراضي بتاريخ 2026-08-22. شغّله فقط ضد بنية تحتية مخوَّل لك اختبارها.
ffmpeg يحتوي على ; أو && أو || أو | أو backtick أو $(. استدعاءات ffmpeg المشروعة من هذا الخادم لا تحتوي على ذلك.sh -c يبدأ سطر أوامرها بـ ffmpeg ويحتوي على أمر ثانٍ بعد فاصل — إشارة على مستوى شجرة العمليات (auditd أو eBPF أو Falco أو EDR) لا تعتمد على سجلات التطبيق.ffmpeg و ffprobe متوقعان؛ أما القشرة أو المفسِّر أو عميل الشبكة فليس كذلك.Running FFmpeg command: ffmpeg <command>، وهو أرخص مكان لرصد قيمة محقونة إذا كانت السجلات تُجمع أصلًا.options أو format أو أو أو على محارف قشرة خاصة.MITRE ATT&CK T1059.004 Command and Scripting Interpreter: Unix Shell.
لا توجد نسخة مُصحَّحة، لذا فالخيارات المتاحة هي الاحتواء والإزالة:
runFFmpegCommand.الإصلاح المنبع (upstream) هو إزالة shell: true وتمرير مصفوفة وسائط إلى ffmpeg — spawn("ffmpeg", ["-i", inputPath, …]) — مع بناء تلك المصفوفة من قيم format و codec و pixelFormat مدرجة في قائمة مسموح بها (allowlist) بدل السلاسل النصية الحرة. التحقق من المحتوى، وليس مجرد التحقق من النوع عبر Zod، هو المتطلب الأساسي.
NIST SP 800-53r5 SI-10; OWASP ASVS v4 §5.3.8; تخفيفات CWE-78 M1 و M2.
aws-mcp-server)إشعارات أمنية مرافقة من نفس جولة البحث: CVE-2026-52616، CVE-2026-52618.
MIT — انظر LICENSE.
| CVE | CVE-2026-52617 |
| CWE | CWE-78 (Improper Neutralization of Special Elements used in an OS Command) |
| الحزمة | @sworddut/mcp-ffmpeg-helper (npm) |
| المتأثر | 0.2.1 وإصدارات سابقة — جميع الإصدارات المنشورة |
| أُصلح في | لا يوجد |
| CVSS v3.1 | AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 7.8 مرتفع (High) (نقل عبر stdio). AV:N → 9.8 حرِج (Critical) إذا كان الخادم مغلَّفًا بنقل شبكي (network transport). |
| أبلغ عنها | s1ko (github.com/s1ko، [email protected]) |
| تخصيص CVE | 2026-07-13، MITRE CNA-LR |
options |
extract_audio | format |
create_video_from_images | codec, pixelFormat, extraOptions |
codecpixelFormatextraOptions| التاريخ | الحدث |
|---|
| 2026-05-29 | تحديد الثغرة عبر مراجعة مصدر الحزمة المنشورة (tarball) |
| 2026-06-01 | تحقق ديناميكي عبر MCP stdio في حاوية معزولة |
| 2026-06-13 | إعادة التحقق على مضيف ثانٍ؛ خاصية الإبلاغ الخاص عن الثغرات (Private Vulnerability Reporting) غير مفعّلة في المستودع، وحقول repository/bugs/homepage في package.json متروكة على قالب github.com/yourusername، فلا تبقى أي جهة اتصال أمنية موثّقة |
| 2026-07-13 | تخصيص MITRE CNA-LR للثغرة CVE-2026-52617، مع نسب الفضل إلى s1ko كمكتشف |
| 2026-08-22 | تأكيد وجود نقطة الضعف مجددًا على الفرع الافتراضي؛ أحدث إصدار على npm ما يزال 0.2.1؛ نُشر هذا التقرير |