
[CVE-2022-22980] حقن تعبير SpEL في Spring Data MongoDB
[CVE-2022-22980] حقن تعبير SpEL في Spring Data MongoDB
MongoDB هي قاعدة بيانات NoSQL موجهة للمستندات، وتتميز بقابلية التوسع والمرونة، وتُستخدم لتخزين كميات كبيرة من البيانات. بدلاً من استخدام الجداول والصفوف كما في قواعد البيانات العلائقية التقليدية، تستخدم MongoDB المجموعات والمستندات. تتكون المستندات من أزواج مفتاح-قيمة، وهي الوحدة الأساسية للبيانات في MongoDB.
Spring Data for MongoDB هو جزء من مشروع Spring Data الشامل الذي يهدف إلى توفير نموذج برمجة مألوف ومتسق قائم على Spring لمخازن البيانات الجديدة مع الحفاظ على الميزات والإمكانيات الخاصة بكل مخزن. يوفر مشروع Spring Data MongoDB التكامل مع قاعدة بيانات المستندات MongoDB. تشمل المجالات الوظيفية الرئيسية لـ Spring Data MongoDB نموذجاً يركز على POJO للتفاعل مع DBCollection في MongoDB وكتابة طبقة وصول إلى البيانات بأسلوب Repository بسهولة.
في 20 يونيو 2022، أصدرت VMware نشرة أمنية على موقعها الرسمي تتعلق بثغرة حقن تعبير SpEL (التي تؤدي إلى تنفيذ التعليمات البرمجية عن بُعد) التي تؤثر على Spring Data MongoDB. يمكنك العثور على معلومات تفصيلية حول ثغرة CVE-2022-22980 أدناه.
الثغرة
يكون تطبيق Spring Data MongoDB عرضة لحقن SpEL عند استخدام طرق استعلام مُعلَّمة بـ @Query أو @Aggregation مع تعبيرات SpEL تحتوي على عناصر نائبة لمعاملات الاستعلام لربط القيم إذا لم يتم تعقيم الإدخال. وبالمثل، فإن الإعدادات التي تعرض طرق استعلام المستودع دون إشراك كود تطبيق إضافي (مثل Spring Data REST) تكون عرضة للخطر أيضاً.
على وجه التحديد، يكون التطبيق عرضة للخطر عندما تتحقق جميع الشروط التالية:
@Query أو @Aggregation تستخدم SpEL (لغة تعبير Spring) وتستخدم مراجع معاملات الإدخال (?0, ?1, …) داخل تعبير SpELلا يكون التطبيق عرضة للخطر إذا تحقق أي مما يلي:
QueryMethodEvaluationContextProvider الذي يحد من استخدام SpELالإصدارات المتأثرة
تتأثر الإصدارات Spring Data MongoDB 3.4.0 و3.3.0 إلى 3.3.4 والإصدارات الأقدم بثغرة CVE-2022-22980 حقن تعبير SpEL في Spring Data MongoDB.
الحالة
تم إصدار Spring Data MongoDB 3.4.1 و3.3.5، والتي تحتوي على الإصلاحات.
التخفيف والحلول البديلة المقترحة
يفضل التحديث إلى Spring Data MongoDB 3.4.1 و3.3.5 أو إصدار أحدث. إذا قمت بذلك، فلن تكون هناك حاجة إلى حلول بديلة. ومع ذلك، قد يكون البعض في موقف يتعذر فيه إجراء الترقية بسرعة. لهذا السبب، قدم فريق Spring بعض الحلول البديلة أدناه.
استخدام صيغة المصفوفة: إذا كان التطبيق يتطلب تعبيرات SpEL ديناميكية يتحكم فيها إدخال المستخدم، فأعد كتابة تعريفات الاستعلام أو التجميع لاستخدام مراجع المعاملات ([0] بدلاً من ?0) داخل التعبيرتنفيذ طريقة مستودع مخصصة: يعد استبدال تعبير SpEL بتطبيق طريقة مستودع مخصصة حلاً بديلاً قابلاً للتطبيق لتجميع الاستعلام الديناميكي داخل كود التطبيق. راجع التوثيق المرجعي حول تخصيص المستودع لمزيد من التفاصيل.تحليل التصحيح: مشكلة GitHub والالتزامات ذات الصلة
يمكن الوصول إلى مشكلة GitHub الخاصة بثغرة حقن SpEL من github.com/spring-projects/spring-data-mongodb/issues/4089.
بفضل الالتزامين أدناه، تم إصلاح الثغرة ذات الصلة.
مع هذه الالتزامات، تمت إضافة الفئة spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/EvaluationContextExpressionEvaluator.java.
class EvaluationContextExpressionEvaluator implements SpELExpressionEvaluator {
ValueProvider valueProvider;
ExpressionParser expressionParser;
Supplier<EvaluationContext> evaluationContext;
public EvaluationContextExpressionEvaluator(ValueProvider valueProvider, ExpressionParser expressionParser,
Supplier<EvaluationContext> evaluationContext) {
this.valueProvider = valueProvider;
this.expressionParser = expressionParser;
this.evaluationContext = evaluationContext;
}
@Nullable
@Override
public <T> T evaluate(String expression) {
return evaluateExpression(expression, Collections.emptyMap());
}
public EvaluationContext getEvaluationContext(String expressionString) {
return evaluationContext != null ? evaluationContext.get() : new StandardEvaluationContext();
}
public SpelExpression getParsedExpression(String expressionString) {
return (SpelExpression) (expressionParser != null ? expressionParser : new SpelExpressionParser())
.parseExpression(expressionString);
}
public <T> T evaluateExpression(String expressionString, Map<String, Object> variables) {
SpelExpression expression = getParsedExpression(expressionString);
EvaluationContext ctx = getEvaluationContext(expressionString);
variables.entrySet().forEach(entry -> ctx.setVariable(entry.getKey(), entry.getValue()));
Object result = expression.getValue(ctx, Object.class);
return (T) result;
}
}

كما تم تعديل الفئة spring-projects/spring-data-mongodb/blob/main/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java على النحو التالي:

النسخة النهائية (المُصلحة) من الفئة spring-projects/spring-data-mongodb/blob/main/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java هي كما يلي:
package org.springframework.data.mongodb.util.json;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;