SnakeYamlの安全でないデシリアライゼーションの脆弱性(CVE-2022-1471)
2022年12月14日
0 分で読めますSnakeYamlは、Java向けのよく知られたYAML 1.1パーサー兼エミッターです。最近、このパッケージに関する脆弱性CVE-2022-1471が報告されました。この脆弱性により、任意のコードが実行される可能性があります。org.yaml:snakeyamlパッケージはJavaエコシステムで広く使われています。その一因は、Spring Bootのspring-boot-starterにデフォルトで含まれていることです。この記事では、このJavaライブラリに影響するセキュリティ脆弱性を詳しく見て、アプリケーションに及ぼす潜在的な危険性を解説し、実際のリスクを検討します。
SnakeYamlのセキュリティ脆弱性とは?
Java向けSnakeYamlライブラリには、Constructorクラスの欠陥に起因する任意コード実行の脆弱性があります。このクラスはデシリアライズできる型を制限していないため、攻撃者が悪意のあるYAMLファイルをデシリアライズさせ、システムを悪用できる可能性があります。そのため、この欠陥は安全でないデシリアライゼーションの問題につながり、任意のコードが実行されるおそれがあります。
SnakeYamlの脆弱性の仕組み
SnakeYamlでYAMLをデシリアライズまたはマーシャリングするのはとても簡単です。一般的には、次のようにします。
上記の例でファイルからYAMLを読み込むと、入力はJavaですべてのObjectのスーパータイプである汎用のObject.classとして解析されます。コードではUserオブジェクトを想定していますが、キャストはObjectがメモリに読み込まれた後に行われます。汎用のObject型であるため、どのようなオブジェクトでも使用できます。アプリケーションのクラスパスにガジェットまたはガジェットチェーンが存在する場合、任意のコードが実行される可能性があります。
これは、記事JavaにおけるシリアライゼーションとデシリアライゼーションおよびJackson ObjectMapperにおけるJava JSONデシリアライゼーションの問題で取り上げた問題と似ています。
SnakeYamlの脆弱性のデモ
脆弱性のある状況を示すため、意図的にガジェットクラスを作成しました。ガジェットとは、インスタンス化されたときに、直接処理を行うか、ガジェットチェーンを開始することで副作用を引き起こすクラスです。この例では、コンストラクターが呼び出されると、ガジェットが指定されたコマンドを実行します。
このJavaクラスを利用できる状態にして、先ほどのコードでYAMLをデシリアライズすると、YAMLファイルに次の内容を入力できます。
つまり、クラスパス上にある任意のJavaクラスをSnakeYamlで標的にできます。そのクラスはすでにクラスパスに存在し、SnakeYamlは想定されたクラスかどうかにかかわらずオブジェクトを作成するため、最終的にClassCastExceptionが発生します。しかし、その時点ですでに被害は発生しており、コマンドは実行されています。クラスパス上にガジェットやガジェットチェーンが存在すると、リバースシェル攻撃のような深刻な事態につながるおそれがあります。
実際のアプリケーションにおけるSnakeYamlの脆弱性の深刻度は?
上記の例のようなガジェットを誰かが作成する可能性は低いでしょう。しかし、サードパーティー製ライブラリを導入すると、そのような方法で他の人が作成したガジェットがコード内に存在する可能性が高まります。ysoserialのGitHubリポジトリや、JSONマーシャリングライブラリjackson-databindのデシリアライゼーションの問題の一覧をざっと見るだけでも、リスクが高いことがわかります。jackson-databindとの違いは、jacksonではデフォルトでdefaultTypingが有効になっていないことです(詳しくは以前の脆弱性に関する記事で説明しています)。
悪意のある攻撃者は、JDK内のクラスを使って被害を与えることもできます。たとえば、ScriptEngineです。
このYAML入力はURLに接続し、アプリケーションに有害なコンテンツをダウンロードできます。詳しくはこちらのWebsecの記事をご覧ください。
もう1つの例として、実行しているJavaのバージョンによっては、LDAPリクエストを利用して検索を行うJdbcRowSetImplクラスがあります。これは、少し前に発生したLog4Shellと同様のリスクを引き起こす可能性があります。
詳しくは、SnakeYamlのBitbucketの課題をご覧ください。
SnakeYamlの脆弱性の影響を受ける?
影響を受けるかどうかは、このライブラリをどのように使用するかによって異なります。XMLやJSONオブジェクトと同じように、別のソースから取得したカスタムYAMLデータを読み込んでいる場合、脆弱性の影響を受ける可能性があります。基本的に、信頼できないソースからの入力は受け付けないでください。
多くの場合、SnakeYamlはSpringやHelidonなどのフレームワークを通じて、システム内にすでに存在するYAML設定ファイルを読み込むために使われます。攻撃者がこれらの設定ファイルを改ざんできるなら、別の、そしておそらくもっと大きな問題が発生しています。ですから、個人的には、この脆弱性の影響はそれほど大きくないと思います。
ライブラリのメンテナーは、この問題に伴うリスクを否定しています。それでも、このようなライブラリがどのように使われているかを予測することはできません。
SnakeYamlの脆弱性に対する推奨緩和策
この記事の公開時点では、このパッケージの新しいバージョンはリリースされていません。メンテナーは、デシリアライズ対象となる特定のアーティファクトをブロックリストに追加するGitプルリクエストを承認しました。この変更は1.34リリースに含まれる見込みです。現時点では、デフォルトの動作に対する汎用的な修正は提供されないようです。
SnakeYamlのドキュメントには、次のように記載されています。信頼できないソースから受け取ったデータに対してYaml.load()を呼び出すのは安全ではありません。メソッドYaml.load()はYAMLドキュメントをJavaオブジェクトに変換します。
以下のように、デフォルトで使用されます。
依存関係を常にスキャンしましょう
ご存じのとおり、アプリケーションのコードの大半はサードパーティー製ライブラリに由来します。すべての開発者がライブラリ内のコードをすべてレビューする時間を確保できるわけではないため、既知の脆弱性がないか依存関係をスキャンすることが重要です。Snykなら、リアルタイムスキャン、実行可能な修正アドバイス、優先度スコアリングにより、修正作業の効果を最大化できます。今すぐ無料アカウントを作成。
CTFを始めよう
オンデマンドのバーチャル入門ワークショップを視聴して、CTFの課題の解き方を学びましょう。
