Log4Shell 脆弱性の対策をした話

# Log4Shell 脆弱性(CVE-2021-44228)の対策をした話

## Log4Shell 脆弱性?
Java製のアプリケーション・ミドルウェアで幅広くつかわれている Log4j2 で、任意のコードを実行できる脆弱性が 2021/12/10(金) に発見され、Log4Shell という名前が付けられたようです。
ログに出力されるであろう箇所（ユーザ名やパスなど）に、jndi lookup を行う文字列を埋め込むだけで実行してしまうもので、容易に当該脆弱性をつけ、危険度の高い（各スコアで最高スコア）状態にあります。

週末ではありましたが、この土日緊急メンテナンスに入るサイトもいくつか見受けられ、業界が素早く対応していました。

脆弱性の内容については、[12/12のサイオスさんの記事](https://security.sios.com/vulnerability/misc-security-vulnerability-20211212.html)がわかりやすかったです。

## 自社の状況

自社では、社内で利用するためにいくつかのサービスを運営しています。
当然その中には、Java製のOSSもあるため、対策しました。

脆弱性の詳細についてはすでに詳しい記事が多く上がっているので、そちらに解説を譲るとして、12/10時点の情報が少ない中でどう動いたかのプロセスを記事にしてみようかと思います。


## 12/10の対応
### 実態把握
情報が錯綜していたので、実態を把握からでした。
12/10時点では、 log4j2の(ほぼ）全バージョンにて問題が発生することがわかっており、その時点で有効な解決策とされたのが、`log4j2.formatMsgNoLookups=true` をJavaのオプションで与えることでした。

log4j2を使うことから、大前提は Java製のアプリケーションであることなので、自社内で利用されているものを列挙しました。Javaは自社開発には利用していないので、調査は社内の業務で利用しているOSSに絞られました（e.g. keycloak, jenkins, elasticsearch)

### 対策深堀
素早く取れる対策は、`log4j2.formatMsgNoLookups=true` であることがわかりましたが、こちらは log4j2 2.10以降で使えるオプションなので、この対策で良しとするには、

1. 当該OSSで利用しているlog4j2 が 2.10 以降である
2. 起動時に Java オプションを指定することができる（する方法がある）

に筋を通す必要がありました。(環境変数で`LOG4J_FORMAT_MSG_NO_LOOKUPS=true` とする方法もあるようですが、12/10 時点では把握できていませんでした。) 

自社内ではDockerでサービス管理しているため、Dockerイメージ対応の脆弱性スキャナ [Trivy](https://github.com/aquasecurity/trivy) を利用しました。

```bash
trivy image --list-all-pkgs jboss/keycloak:13.0.1
```

結果 (結果例を示すために、今再度実行したので、対応版が `2.15.0` となっていますが…当時はまだ正式対応版は出ていませんでした):

```plaintext
+--------------------------------------------------------------------+------------------+----------+-------------------------+--------------------------------+---------------------------------------+
| org.apache.logging.log4j:log4j-api                                 | CVE-2021-44228   | CRITICAL | 2.14.0                  | 2.15.0                         | log4j-core: Remote code execution     |
|                                                                    |                  |          |                         |                                | in Log4j 2.x when logs contain        |
|                                                                    |                  |          |                         |                                | an attacker-controlled...             |
|                                                                    |                  |          |                         |                                | -->avd.aquasec.com/nvd/cve-2021-44228 |
+--------------------------------------------------------------------+------------------+----------+-------------------------+--------------------------------+---------------------------------------+
```

こちらのように、利用しているイメージを与えると、利用しているパッケージが出てくるのでこちらで判断しました。12/10時点で自社内でlog4j2を利用しているサービスは全て 2.10 より新しかったので今回はJavaのオプション指定で暫定対策することにしました。

### サービス毎の対策
個別のサービスについては、Javaオプションの与え方が異なりますので、それぞれ調べていきました。[DockerHub/Keycloak](https://hub.docker.com/r/jboss/keycloak/) など、イメージの公式ページを見ると、Javaの実行時オプションを与える方法が書いてあることが多いので、そちらを参照しました。


例えば、`tomcat`イメージで動くものであれば、環境変数`JAVA_OPTS`が起動時に与えられるので、`docker-compose.yml`で、

```yaml
    environment:
        JAVA_OPTS: -Dlog4j2.formatMsgNoLookups=true
```

と指定し、`keycloak`イメージであれば、

```yaml
    environment:
        JAVA_OPTS_APPEND: -Dlog4j2.formatMsgNoLookups=true
```

といった具合に、どういう手順でJavaの起動オプションが指定されるのかイメージ毎に調べて記載しました。
(後になって、`LOG4J_FORMAT_MSG_NO_LOOKUPS`環境変数を設定すればよいことがわかりました）

## その後

対応後もログや、実行プロセスなどを確認し、不自然な動きがないか見ていました。
12/12のAMに、数回今回の脆弱性を試すリクエストが送られて、その後何度も手を変え品を変え試行が来てました。
乗っ取られたりとか不自然なプロセスはなさそうなので、今のところは大丈夫そうです。

しばらく、業界的に騒然としますね…
今日(12/13)には対策版の log4j2 2.15.0 の正式リリースも出たようで、関係各位の奮闘には頭が上がりません。

今後数日以内には、著名なOSSは正式対応版を取り込んだバージョンがリリースされるだろうから、本質的な対策として、それらを取り込んでいこうかと思います。