OpenSSH(CVE2024-6387)のパッチ当て対応の反省メモ

記事タイトルとURLをコピーする

Security Hubになりたい山本拓海です。

CVE2024-6387にはregreSSHion という通称があります

先日公表されたOpenSSHの脆弱性(CVE2024-6387)のパッチ当て対応をしました。対応した環境ではセキュリティ緊急対応のマニュアルがなかったので、手順から検討し実施しました。
その際の反省メモを残し、今後に活かしたいと思います。

作業じゃない部分の反省点

いきなり本題からずれるのですが、今回脆弱性のニュースをキャッチアップできたのは偶然でした。
社内Slackの雑談系のチャンネルを見ていたら脆弱性に関する情報が流れてきて、対応が必要になるかもと思い実施したという流れです。

この反省点として、脆弱性情報は必ず見る仕組みが必要だなと思いました。

なんですが、CVEの1次情報のFeedってかなりの量になので、さばくのがかなり大変なのと、 NVDの情報更新も停滞している状態のようなので、常にベストな方法というのが現状よくわかりません。 とりあえずJVN 脆弱性レポートを毎日読む習慣つけるようにしてみます。

jvn.jp

今回実施したこと

本題に戻ります。今回実施したことは以下の通りです。

  • 70アカウント300台のEC2の利用OS調査
  • OSごとの対応方法の調査
  • Systems Manager Run Commandを使ったパッチ当て

実施したこと① 70アカウント300台のEC2の利用OS調査

実施前のOS調査には、チームメンバーが用意していたマネージドインスタンスの資料にお世話になりました。 作成にはConfig Aggregatorを利用します。Config Aggregatorの利用の設定は以下の佐竹の記事に詳細な記載があります。

blog.serverworks.co.jp

具体的には、Config Aggregatorで リソースタイプ SSM::ManagedInstanceInventory を対象にクエリするとOSの情報を取得できるので、この情報から全マネージドインスタンスの対応の要否を判断しました。
今回のリストを作る場合、出力されるデータ構造がシェルスクリプトだけで書くには若干面倒な構造です。私が書いたpythonコードの一部を抜粋しました。boto3を使っています。

    # クライアント初期化
    client = session.client('config')

    # ページネーター初期化
    paginator = client.get_paginator('select_aggregate_resource_config')
    response_iterator = paginator.paginate(
        Expression = "SELECT awsRegion, accountId, tags, resourceId, configuration WHERE resourceType = 'AWS::SSM::ManagedInstanceInventory'",
        ConfigurationAggregatorName = '${AGGREGATOR_NAME}'
    )

    data = []
    for page in response_iterator:
    # 取得できる結果ごとの処理
        for item in page['Results']:
            item = json.loads(item)
    # リソースIDがキーになっているので、変数を使いたい
            resource_id = item['resourceId']
            content = item['configuration']['AWS:InstanceInformation']['Content'][resource_id]
            data.append([
                item['accountId'],
                resource_id,
                item['awsRegion'],
                content['PlatformName'],
                content['PlatformVersion'],
                content['InstanceStatus'],
                content['ComputerName'],
                content['IpAddress'],
                content['PlatformType'],
            ])

また、マネージドインスタンス以外のEC2は、同じくConfig Aggregatorでリソースタイプ EC2::Instanceを対象にクエリして非マネージドインスタンスのリストを作成後、マネジメントコンソールの画面上から各インスタンスのAMIを見て調査しました。

AMIがオフィシャルではなく、且つ既に削除している場合、AMIからOSを知る方法が難しいので、 場合によりインスタンスにログインして確認が必要なケースもあるかもしれません。

反省点

この部分には特に反省点はなく、スムーズに進められました。

実施したこと② OSごとの対応方法の調査

公開されている情報から各OSごとの対応方法を調査しました。 Amazon Linuxは以下のサイトから確認しました。

explore.alas.aws.amazon.com

その他のOSはpiyokangoさんのサイトから各OSの対応方法を確認しました。

piyolog.hatenadiary.jp

反省点

1つ目の反省点は、対象OSの勘違いです。
最初の情報源としてAmazon Linux Security Centerを参考にしていたためか、対象OSはAL2023だけという勘違いしてしまい、SUSEやubuntuにも対象のバージョンがあることが考慮から漏れてしまってました。対象のOSの確認や調査内容は、一人だけで対応せずに信頼できるメンバーと相談しながら進めるのがよさそうです。

2つ目の反省点は、対象バージョンの誤認識です。
Config Aggregatorで取得したOS情報から稼働しているSUSEやubuntuは脆弱性の影響を受けるバージョンであると認識したのですが、これが誤認識でした。
対応を進めるとデプロイされているバージョンは脆弱性の影響を受けないエディションだったということや、バージョンが番号ではなくコードネームで記載されていて対象かどうかわかりにくいということもありました。 こちらも自信がない場合、詳しい方に確認を依頼するのが良いかと思います。作業の一部をアウトソースすることで、先行して一部のOSのパッチ当てを実施するようなパラレルでの進め方も期待できますし、脆弱性の影響を受けるバージョンかどうかを確認するのはけっこうリソースを食います。

実施したこと③ Systems Manager Run Commandを使ったパッチ当て

Systems Manager Run CommandにあるAWS-RunPatchBaselineを使って、パッチ当てを実施できる想定でいました。実行時のオプションを"Scan"とするとインストールができてないことはわかるのですが、"Install"としてもインストールができませんでした。
気になったのですが、アップデートを進めることを優先し、AWS-RunShellScriptでdnfコマンドを利用して、ライブラリの確認とアップデートを実施するよう進めました。

また、RHEL9のインスタンスでは dnfコマンドを実行してもrepoファイルが404エラーとなり、アップデートが実行できませんでした。 ここも原因は不明でしたが、アップデートを進めることを優先として、yumコマンドでの更新を行いました。

実施中の2つ不明点があったのでなぜこうなったか原因を確認します。

不明点1. RunPatchBaselineで最新版のOpenSSHのインストールができなかった理由

このブログを書く際にAWS-RunPatchBaselineを再度実行したところ、問題なくインストールできました。 改めていろいろと確認すると、これは参照するパッチベースラインに起因していたようです。

パッチベースラインはAWSマネージドのものと、詳細な要件をユーザが設定したカスタムパッチベースラインがあり、初期設定ではAWSマネージドのパッチベースラインがデフォルトパッチベースラインとして設定されています。AWS-RunPatchBaseline実行時に参照するのはデフォルトパッチベースラインです。

赤はAWSマネージドのパッチベースライン、緑はカスタムパッチベースライン

カスタムパッチベースライン作成時にユーザが設定できる詳細な要件の中に、「指定した日数後にパッチを承認する」という設定があります。 ここでは、パッチがリリースされてから何日後のものをベースラインに含めるかを設定できます。

指定した日数後にパッチを承認する の設定

AWSマネージドのデフォルトパッチベースラインではこの日数が7日になっています。

AWSマネージドのパッチベースラインの設定値

今回インストールされることを予想していた最新版のOpenSSHは、7/3の時点でリリースから2日しか経っていない状態です。そのためインストールができなかったようです

解決方法として、カスタムパッチベースラインをデフォルトパッチベースラインとすることで、AWS-RunPatchBaselineにてパッチ適応が可能です。次回以降はこちらの方法も検討します。

カスタムパッチベースラインをデフォルトパッチベースラインとして設定可能

不明点2. dnfコマンドではrepoファイルが404となるが、yumではアップデートができた理由

こちらの不明点は再現でき、原因を色々と調査しましたが、明確な理由に辿り着けていません。

ただ、不明点1の原因がわかったのでRHEL9のインスタンスに対しても同じくAWS-RunPatchBaselineを実行してみたところ、OpenSSHが問題なくインストールできました。 なので、dnfコマンドAWS-RunShellScriptを実施する前に、カスタムパッチベースラインを作成してAWS-RunPatchBaselineを実行することで問題を回避するのがよいかと考えています。

反省点

実施内容に関する反省点ではないのですが、実施後にこの脆弱性対応のスピード感に妥当性はあったのだろうかと考えました。
現在もKEVにこの脆弱性に対するエクスプロイトコードが公表されていないこともあり、もし定期的にパッチ適応をする運用体制があれば、このスピード感で対応しなくてもよかったのではと考えています。
また、この対応後に毎日脆弱性情報を眺めていると、毎日CRITICALやHIGHな脆弱性が公表されています。それらの脆弱性への対応も必要です。
堅牢に環境を運用するためには定期的なパッチ適応をすることが大事だということを改めて認識しました。

最後に

今回OpenSSHの脆弱性対応アップデート時に行った対応内容と反省点は以上となります。 運用をしている環境でいつクリティカルな脆弱性が発生するかは予想ができません。そのような緊急時の対応方法の整理をしておくのが肝要なのですが、もしものための対応なのでどうしても後回しにせざるを得ません。
そのようなときに参考になれば幸いです。