hotpatch-for-apache-log4j を無効化する方法を検証してみた

AWSからlog4j2の脆弱性対策として提供されているhotpatch-for-apache-log4jがインストールされた環境でこのパッチを無効化する方法を検証しました。
2021.12.22

はじめに

log4j2の脆弱性(CVE-2021-44228)の対策としてAWSからパッチがリリースされています。このパッチは起動中のJVMを検出してパッチ済みのクラスファイルを送り込むことで脆弱性を回避するものです。しかし起動しているJVMプロセスにクラスファイルのロードを行うのは避けたい場合もあると思います。今回はこのパッチを無効化する方法を検証してみました。

Amazon Linuxで提供されているJVMとパッチの関係

このパッチは現在 Amazon CorrettoおよびAmazon Linuxによって提供されるOpenJDKのセキュリティアップデートとしてJVMともにインストールされるため、新たにこれらのパッケージをインストールしたりインスタンス起動時のアップデートでパッチがインストールされます。各パッケージのアップデートの詳細は以下の参考リンクを参照してください。

参考: Amazon Linux Hotpatch Announcement for Apache Log4j

パッチを無効化する

パッチを無効化する方法はこのアナウンスで紹介されています。

If you need to disable the hotpatch, this can be done by running sudo touch /etc/log4j-cve-2021-44228-hotpatch.kill. This will create a file that the hotpatch service will detect and will not attempt to apply the hotpatch to any running JVM it finds.

Correttoインストール済みのAMI(作成方法は後述) からAutoScaling Groupなどでインスタンスを自動起動する場合にパッチの無効化を自動で行う方法をいくつか検証してみます。

結論から言うとインスタンス起動時にパッチを無効化するには後者のkill fileを含めておく方法だけが有効でした。

検証するパターン

  • userdataでkill fileを作成
  • AMIにkill fileを含めておく

userdataでkill fileを作成

以下のようなスクリプトをuserdataに設定します。

#!/bin/bash

touch /etc/log4j-cve-2021-44228-hotpatch.kill

起動後にログを確認します。

ip-172-31-19-248 はAMI作成時のインスタンスのIPアドレス、ip-172-31-25-154 は検証用に起動したインスタンスのIPアドレスです。検証用のインスタンスでも起動時にパッチが動作していることがわかります。これはuserdataのスクリプトが実行されるよりも前にパッチ用のスクリプトが起動するためです。

sh-4.2$ sudo less /var/log/messages  | grep log4j
Dec 22 11:05:08 ip-172-31-19-248 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] Starting up now...
Dec 22 11:05:08 ip-172-31-19-248 yum[3333]: Installed: log4j-cve-2021-44228-hotpatch-1.1-9.amzn2.noarch
Dec 22 11:05:08 ip-172-31-19-248 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] No JVMs found, exiting gracefully
Dec 22 11:08:36 ip-172-31-25-154 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] Starting up now...
Dec 22 11:08:37 ip-172-31-25-154 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] No JVMs found, exiting gracefully

プロセスを確認してみるとパッチ用のスクリプトが起動しています。

sh-4.2$ ps axu | grep log4j
root      2553  0.0  0.3 124204  3144 ?        Ss   11:08   0:00 /bin/bash /usr/bin/log4j-cve-2021-44228-hotpatch -w 1800 -m 10
ssm-user  5943  0.0  0.0 119424   956 pts/0    S+   11:15   0:00 grep log4j

AMI内にkill fileを作成しておく

同様にログを確認するとFound kill file, not applying patch. というログが出力されてパッチの適用が行われていないことがわかります。

sh-4.2$ sudo less /var/log/messages | grep log4j
Dec 22 11:11:28 ip-172-31-31-245 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] Starting up now...
Dec 22 11:11:28 ip-172-31-31-245 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] No JVMs found, exiting gracefully
Dec 22 11:11:28 ip-172-31-31-245 yum[3350]: Installed: log4j-cve-2021-44228-hotpatch-1.1-9.amzn2.noarch
Dec 22 11:33:54 ip-172-31-28-170 log4j-cve-2021-44228-hotpatch: [log4j-hotpatch] Found kill file, not applying patch.

こちらでもスクリプトは起動しています。(kill fileがあるのにスクリプトが起動している理由は本稿の後半「参考情報」を参照)

sh-4.2$ ps axu | grep log4j
root      2563  0.0  0.3 124204  3160 ?        Ss   11:33   0:00 /bin/bash /usr/bin/log4j-cve-2021-44228-hotpatch -w 1800 -m 10
ssm-user 10679  0.0  0.0 119424   940 pts/0    S+   11:54   0:00 grep log4j

このパターンで使ったpackerでのプロビジョニングスクリプトは以下になります。packerの設定ファイルは参考情報の「Correttoを含むAMIを作成する」に掲載しています。

#!/bin/bash

sudo yum install -y java-11-amazon-corretto-headless
sudo touch /etc/log4j-cve-2021-44228-hotpatch.kill

まとめ

取り急ぎですが、パッチを自動で無効化する方法を検証してみました。

参考情報

Correttoを含むAMIを作成する

packerでCorrettoを含むAMIを作成します。使用するスクリプトは下記の通りです。

packer JSON

{
  "builders": [
    {
      "type": "amazon-ebs",
      "region": "ap-northeast-1",
      "source_ami": "ami-0218d08a1f9dac831",
      "ami_name": "AL2 with coretto with log4jpatch",
      "instance_type": "t2.small",
      "ssh_username": "ec2-user",
      "ssh_timeout": "5m",
      "ssh_pty": true
    }
  ],
  "provisioners": [
    {
      "type": "shell",
      "scripts": [
        "scripts/install_java.sh"
      ]
    }
  ]
}

scripts/install_java.sh

#!/bin/bash
sudo yum install -y java-11-amazon-corretto-headless

記事執筆時点(2021/12/22) でインストールされるパッケージの情報は下記の通りです。このバージョンではパッチが一緒にインストールされます

sh-4.2$ sudo yum info java-11-amazon-corretto-headless
Loaded plugins: extras_suggestions, langpacks, priorities, update-motd
Installed Packages
Name        : java-11-amazon-corretto-headless
Arch        : x86_64
Epoch       : 1
Version     : 11.0.13+8
Release     : 2.amzn2
Size        : 304 M
Repo        : installed
From repo   : amzn2-core
Summary     : Amazon Corretto headless development environment
URL         : https://github.com/corretto/corretto-11
License     : ASL 1.1 and ASL 2.0 and BSD and BSD with advertising and GPL+ and GPLv2 and GPLv2 with exceptions and IJG and LGPLv2+ and MIT and MPLv2.0 and
            : Public Domain and W3C and zlib and ISC and FTL and RSA.
Description : Amazon Corretto's packaging of the runtime core elements of the
            : OpenJDK 11 code. (Headless environment)

パッチ用スクリプトが常に起動している理由

パッチ用の起動スクリプトはサービスとして起動してパッチを適用した後一定時間スリープして終了し、systemdによって再度起動されます。そのためパッチを行っていない時でもスクリプトが動作しています。このスクリプトやサービスの設定定義は以下で参照できます。

rpm -ql log4j-cve-2021-44228-hotpatch
/usr/bin/log4j-cve-2021-44228-hotpatch
/usr/lib/systemd/system/log4j-cve-2021-44228-hotpatch.service
/usr/share/log4j-cve-2021-44228-hotpatch/jdk11/Log4jHotPatch.jar
/usr/share/log4j-cve-2021-44228-hotpatch/jdk17/Log4jHotPatchFat.jar
/usr/share/log4j-cve-2021-44228-hotpatch/jdk8/Log4jHotPatch.jar