
[CVE-2022-22980] Injeção de Expressão SpEL no Spring Data MongoDB
[CVE-2022-22980] Injeção de Expressão SpEL no Spring Data MongoDB
MongoDB é um banco de dados NoSQL orientado a documentos, com a escalabilidade e flexibilidade usadas para armazenamento de grandes volumes de dados. Em vez de usar tabelas e linhas como nos bancos de dados relacionais tradicionais, o MongoDB utiliza coleções e documentos. Os documentos consistem em pares de chave-valor, que são a unidade básica de dados no MongoDB.
Spring Data for MongoDB faz parte do projeto guarda-chuva Spring Data, que visa fornecer um modelo de programação familiar e consistente baseado no Spring para novos datastores, mantendo os recursos e capacidades específicos de cada armazenamento. O projeto Spring Data MongoDB fornece integração com o banco de dados de documentos MongoDB. As principais áreas funcionais do Spring Data MongoDB são um modelo centrado em POJO para interagir com um DBCollection do MongoDB e escrever facilmente uma camada de acesso a dados no estilo Repository.
Em 20 de junho de 2022, a VMware publicou um aviso de segurança em seu site oficial relacionado à vulnerabilidade de Injeção de Expressão SpEL (que leva à execução remota de código) que afeta o Spring Data MongoDB. Você pode encontrar informações detalhadas sobre a vulnerabilidade CVE-2022-22980 logo abaixo.
Vulnerabilidade
Uma aplicação Spring Data MongoDB é vulnerável a Injeção de SpEL quando utiliza métodos de consulta anotados com @Query ou @Aggregation com expressões SpEL que contêm placeholders de parâmetros de consulta para ligação de valores, se a entrada não for sanitizada. Alternativamente, configurações que expõem métodos de consulta do repositório sem envolver código adicional da aplicação (como o Spring Data REST) também são vulneráveis.
Especificamente, uma aplicação é vulnerável quando todas as seguintes condições são verdadeiras:
@Query ou @Aggregation que faz uso de SpEL (Spring Expression Language) e usa referências a parâmetros de entrada (?0, ?1, …) dentro da expressão SpELUma aplicação não é vulnerável se qualquer uma das seguintes condições for verdadeira:
QueryMethodEvaluationContextProvider que limita o uso de SpELVersões Afetadas
Spring Data MongoDB 3.4.0, 3.3.0 a 3.3.4 e versões anteriores são afetadas pela vulnerabilidade CVE-2022-22980 Spring Data MongoDB SpEL Expression Injection.
Status
Spring Data MongoDB 3.4.1 e 3.3.5, que contêm as correções, foram lançados.
Mitigação e Soluções Alternativas Sugeridas
A resposta preferida é atualizar para o Spring Data MongoDB 3.4.1 e 3.3.5 ou superior. Se você já fez isso, nenhuma solução alternativa é necessária. No entanto, alguns podem estar em uma posição em que a atualização é impossível de ser feita rapidamente. Por esse motivo, a equipe do Spring forneceu algumas soluções alternativas abaixo.
Usando a sintaxe de array: se a aplicação exigir expressões SpEL dinâmicas que sejam controladas pela entrada do usuário, reescreva as declarações de consulta ou agregação para usar referências de parâmetro ([0] em vez de ?0) dentro da expressãoImplementando um método de repositório customizado: Substituir a expressão SpEL por uma implementação de método de repositório customizado é uma solução alternativa viável para montar sua consulta dinâmica dentro do código da aplicação. Consulte a documentação de referência sobre customização de repositórios para mais detalhes.Análise do Patch: Issue no GitHub e Commits Relacionados
A issue no GitHub para a vulnerabilidade de injeção de SpEL pode ser acessada em github.com/spring-projects/spring-data-mongodb/issues/4089.
Com a ajuda dos dois commits abaixo, a vulnerabilidade relacionada foi corrigida.
Com esses commits, a classe spring-data-mongodb/src/main/java/org/springframework/data/mongodb/util/json/EvaluationContextExpressionEvaluator.java foi adicionada.
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;
}
}
