サーバーをセキュアに保つには、まず「何が動いていて、何がインストールされているか」を知る必要があります。把握していないものは、更新も削除もできないからです。

この記事では、Amazon Linux 2023(以下 AL2023)の状態を確認する手順と、確認したあとにパッチを当てる・バージョンを上げる手順をまとめます。Ubuntu 版の記事と同じ流れで、apt を dnf / rpm に置き換えています。1〜5 章のコマンドはすべて読み取り専用です。システムを変更するのは 6 章と 7 章です。7 章では、2026 年 10 月に公開された PHP の脆弱性「PHP2Shell」を例に、特定のソフトウェアだけを緊急で更新する流れを追います。

各コードブロックの上に Command(入力するもの)と Output(表示される結果)の見出しを付けています。 出力例は AL2023 の表示形式に合わせた説明用の例です。ホスト名・パッケージの一覧・バージョン・ALAS の番号などは、実際の値とは異なります。

Ubuntu との主な違い#

AL2023 は Fedora / RHEL 系のディストリビューションで、パッケージ管理は dnf(内部は rpm)です。Ubuntu の apt と、考え方は似ていますが、次の点が違います。

項目UbuntuAL2023
パッケージ形式.deb.rpm
低レベルのツールdpkg / dpkg-queryrpm
高レベルのツールaptdnf
セキュリティ情報USN、Ubuntu CVE トラッカーALAS(Amazon Linux Security Advisory)、Amazon Linux Security Center
更新の対象になるリポジトリ最新のリポジトリを常に見るリリース(releasever)ごとに固定される
リリースの更新do-release-upgrade同じ AL2023 の中で --releasever を進める。メジャーバージョンの更新(AL2 から AL2023 など)は新しいインスタンスに移行する
自動更新unattended-upgrades が標準で有効標準では設定されていない。dnf-automatic を自分で設定する

特に重要なのが リリースの固定 です。AL2023 は、リポジトリの内容をリリースごとに固定する仕組み(決定論的アップグレード)になっています。そのため、dnf upgrade だけでは、今のリリースより新しい修正が入らないことがあります。詳しくは 6 章で説明します。

RHEL や Rocky Linux でも同じか#

AL2023、RHEL(Red Hat Enterprise Linux)、Rocky Linux は、どれも Red Hat 系で、パッケージ形式は RPM、管理ツールは dnf です。この記事のコマンドの多くは、RHEL や Rocky Linux でも同じように使えます。

  • そのまま使えるもの: rpm -qa --qf ...、rpm -qf、rpm -V、dnf list installed、dnf repoquery、dnf history、dnf check-update、dnf upgrade --security、dnf upgrade --assumeno、dnf needs-restarting
  • 考え方も同じ: バックポートがあるので、バージョン番号ではなく changelog で CVE を確認する。ソース RPM で対象を特定する。更新したらサービスを再起動する。バージョンの末尾は、amzn2023 ではなく el9 のようになる。

ただし、次の点は違います。

項目AL2023RHELRocky Linux
リリースの固定(--releasever)あり。自分で進めるなしなし
更新の追従固定したリリースの範囲内メジャーバージョン内(9.x など)の最新まで、通常の dnf upgrade で進む同左
セキュリティ情報ALASRHSARLSA
更新の取得追加の登録は不要サブスクリプションの登録が必要不要
SELinux の標準PermissiveEnforcingEnforcing
メジャーバージョンの更新新しいインスタンスに移行leapp によるインプレース更新ELevate などの外部ツール

この記事の リリースの固定 の説明(dnf check-release-update、--releasever=latest)は、AL2023 特有で、RHEL と Rocky Linux には当てはまりません。RHEL と Rocky Linux では、通常の dnf upgrade で最新まで進みます。

また、PHP のようなパッケージの名前も、ディストリビューションで違います。RHEL / Rocky Linux では、AppStream のモジュール(php:8.3 など)で管理されることが多く、7 章の PKGS を取り出す正規表現は、そのまま使えません。

確認する順番#

次の順に見ていくと整理しやすくなります。

  1. OS とカーネル
  2. インストール済みパッケージ
  3. dnf の管理外のもの
  4. パッケージのバージョンと修正状況
  5. 更新状況・サービス・ポート・ユーザー
  6. パッチ適用とバージョンアップ
  7. 事例: PHP2Shell に対応する

1. OS とカーネルの情報#

OS のバージョンを確認します。

Command

cat /etc/os-release

Output(抜粋)

NAME="Amazon Linux"
VERSION="2023"
ID="amzn"
ID_LIKE="fedora"
VERSION_ID="2023"
PLATFORM_ID="platform:al2023"
PRETTY_NAME="Amazon Linux 2023.9.20261020"

PRETTY_NAME の 2023.9.20261020 が、今のリリース です。この値が、あとで出てくる releasever になります。

リリースの詳細は、次のコマンドでも確認できます。

Command

cat /etc/system-release
rpm -q system-release

Output

Amazon Linux release 2023.9.20261020 (Amazon Linux)
system-release-2023.9.20261020-1.amzn2023.noarch

カーネルのバージョンを確認します。

Command

uname -r

Output

6.1.158-180.294.amzn2023.aarch64

最後の aarch64 は CPU のアーキテクチャです(Intel / AMD なら x86_64)。起動してからの時間と、再起動の履歴も確認します。

Command

uptime -p
last reboot | head -3

Output

up 47 days, 3 hours, 12 minutes
reboot   system boot  6.1.158-180.294. Mon Sep  8 02:11   still running
reboot   system boot  6.1.150-174.273. Thu Jul 24 02:09 - 02:08 (45+23:59)

長い間再起動していないサーバーは、カーネルの更新が適用されていない可能性があります。今動いているカーネルと、入っているカーネルのパッケージを比べるのは、6 章で行います。

サポート期限(EOL)を確認する#

OS のサポートが終わると、セキュリティ修正が配信されなくなります。パッチを当てる以前に、今の OS がいつまでサポートされるか を確認します。

OSサポートの終了
Amazon Linux 22026 年 6 月 30 日に終了済み。標準のセキュリティ更新は配信されない
Amazon Linux 2023標準サポートが 2027 年 6 月 30 日まで、メンテナンスが 2029 年 6 月 30 日まで
RHEL 8(参考)メンテナンスサポートが 2029 年 5 月 31 日まで
RHEL 9(参考)メンテナンスサポートが 2032 年 5 月 31 日まで

AL2023 のサポートは、2 つの段階に分かれています。

  • 標準サポート(〜2027 年 6 月 30 日): 四半期ごとのマイナーバージョンの更新(新しい機能やパッケージを含む)と、セキュリティ修正が提供されます。
  • メンテナンス(〜2029 年 6 月 30 日): セキュリティ修正と重大なバグ修正だけが提供されます。新しい機能やパッケージは増えません。

つまり、AL2023 は 2027 年 6 月以降、PHP などの新しいバージョンが入らなくなります。アプリが新しいランタイムを必要とするなら、それより前に次の OS への移行を計画します。Amazon Linux 2 を使っている場合は、すでにサポートが終了しているので、AL2023 への移行を優先します。

RHEL の日付は参考です。Rocky Linux は RHEL のライフサイクルに沿っています。最新の日付は、Red Hat と Rocky Linux の公式のライフサイクルのページで確認してください。

AL2023 では、入っているパッケージごとのサポート状況 も、dnf で確認できます。

Command

sudo dnf supportinfo --pkg php8.4
sudo dnf supportinfo --show installed

OpenSSL、OpenSSH、glibc、dnf などのコアパッケージは、AL2023 の寿命の間サポートされます。それ以外のパッケージは、上流のプロジェクトのサポート期限に従います。たとえば PHP は、上流のサポートが終わると、AL2023 でも修正が配信されなくなります。OS のサポートが続いていても、個別のパッケージが先にサポート切れになることがある ので、supportinfo で確認します。

2. インストール済みパッケージ#

dnf list の使い方#

インストール済みのパッケージを一覧します。

Command

dnf list installed

Output(抜粋)

Installed Packages
acl.aarch64                     2.3.1-4.amzn2023.0.2        @System
amazon-ssm-agent.aarch64        3.3.1611.0-1.amzn2023       @amazonlinux
bash.aarch64                    5.2.15-1.amzn2023.0.2       @System
openssl.aarch64                 1:3.0.8-1.amzn2023.0.18     @System

右端の列は、パッケージの取得元です。@System は取得元が記録されていないもの(最初から入っていたもの)、@amazonlinux は AL2023 の標準リポジトリから入れたものです。

件数を数えます。

Command

rpm -qa | wc -l

Output

412

dnf list installed は先頭の見出しの行があるので、rpm -qa の方が数えやすいです。

インストール済みの中から、特定のものだけを探すこともできます。

Command

dnf list installed 'python3*' | head -5

Output

Installed Packages
python3.aarch64                 3.9.25-1.amzn2023.0.1       @System
python3-dnf.noarch              4.14.0-1.amzn2023.0.6       @System
python3-libs.aarch64            3.9.25-1.amzn2023.0.1       @System

同じパッケージの、リポジトリにあるバージョンをすべて表示します。

Command

dnf list --showduplicates openssl

Output

Installed Packages
openssl.aarch64     1:3.0.8-1.amzn2023.0.18     @System
Available Packages
openssl.aarch64     1:3.0.8-1.amzn2023.0.18     amazonlinux

「Available」に新しいバージョンがあれば、更新できます。ただし、AL2023 では 今のリリースで見えている範囲 に限られます(6 章)。

rpm -qa と dnf list installed の違い#

どちらもインストール済みのパッケージを一覧できます。Ubuntu の dpkg-query と apt list --installed の関係と、同じです。

rpm -qadnf list installed
情報の出どころrpm のデータベースだけrpm のデータベースに加え、dnf の履歴
出力形式--qf で自由に指定できるほぼ固定(名前・バージョン・取得元)
出力の安定性安定していて、スクリプト向き見出しの行や列の幅が変わる可能性がある
取得元(リポジトリ)分からない分かる(@amazonlinux など)
手動/自動の区別分からない分からない(dnf repoquery --userinstalled で別に確認する)
ソース RPM 名、サイズ取れる取れない

「インストール済みのパッケージを確認する」という目的では、どちらも同じ結果になります。更新後にバージョンを確認するだけなら、どちらを使っても確認できます。

使い分けの目安は、人が目で見るなら dnf list installed、スクリプトで処理や比較をするなら rpm -qa --qf ... です。

サイズの大きいパッケージを見る#

容量の大きいものから並べると、そのマシンが何に使われているかがだいたい分かります。

Command

rpm -qa --qf '%{SIZE}\t%{NAME}\n' | sort -rn | head -8 | numfmt --to=iec --field=1

Output

209M    ansible-core
141M    kernel-modules-core
128M    docker
113M    glibc-all-langpacks
104M    python3-botocore
 97M    containerd
 61M    mesa-vulkan-drivers
 55M    gcc

一般に、カーネルモジュール、コンテナ基盤、コンパイラ一式、構成管理ツールなどが上位に来やすいです。

セキュリティの観点では、次のようなものに目を向けます。

  • コンテナ基盤(Docker など): docker グループに入っているユーザーは、実質 root と同じ権限を持ちます。
  • コンパイラ: 侵入された場合に、攻撃者がツールをビルドする手段になります。使わないなら削除を検討します。
  • GUI 向けのライブラリ: GUI を使わないサーバーでは、不要なことが多いです。

あるパッケージが何に必要とされているかは、次のコマンドで確認できます。

Command

dnf repoquery --installed --whatrequires openssl

Output

ca-certificates-0:2023.2.68-1.amzn2023.0.1.noarch
cloud-init-0:23.4.4-1.amzn2023.0.3.noarch
curl-0:8.11.1-1.amzn2023.0.1.aarch64

何も表示されなければ、ほかのパッケージからは依存されていません。

3. 「手動インストール」の意味に注意#

自分で入れたパッケージは次のコマンドで一覧にできます。

Command

dnf repoquery --userinstalled

Output(抜粋)

amazon-ssm-agent-0:3.3.1611.0-1.amzn2023.aarch64
bash-0:5.2.15-1.amzn2023.0.2.aarch64
cloud-init-0:23.4.4-1.amzn2023.0.3.noarch
curl-minimal-0:8.11.1-1.amzn2023.0.1.aarch64

ここでの「ユーザーがインストールした」は、dnf が管理しているパッケージのうち、名前を指定してインストールしたもの という意味です。「dnf 以外の方法で入れたもの」という意味ではありません。依存関係として自動で入ったパッケージは表示されません。AMI を作ったときに入ったもの(bash など)も含まれます。

入れ方--userinstalled に出るか
dnf install <名前> で指定した出る(依存で入ったものは出ない)
追加のリポジトリから dnf install した出る
.rpm を rpm -i や dnf install ./x.rpm で入れた出る
ソースから make install した出ない
pip / npm / cargo などで入れた出ない
バイナリを置いただけ出ない

注意が必要なのは dnf の管理外 のものです。dnf check-update に出てこないため、更新を自分で追いかけないと、古く脆弱なまま残ってしまいます。

いつ、どのコマンドで入れたかは、dnf の履歴に残っています。

Command

dnf history list | head -6

Output

ID     | Command line                          | Date and time    | Action(s)      | Altered
-------------------------------------------------------------------------------------------
    12 | upgrade --releasever=2023.9.20261020  | 2026-10-24 06:38 | Upgrade        |   31
    11 | install php8.4-cli                    | 2026-10-20 10:12 | Install        |    7
    10 | upgrade                               | 2026-10-01 03:00 | Upgrade        |   12

dnf の管理外のものを探す#

/usr/local や /opt に置かれたものは、パッケージ管理の外にあります。

Command

ls /usr/local/bin /opt

Output

/usr/local/bin:
terraform  kubectl

/opt:
aws

見つけたファイルが、パッケージに属しているかを確認します。

Command

rpm -qf /usr/local/bin/terraform /usr/bin/curl

Output

file /usr/local/bin/terraform is not owned by any package
curl-minimal-8.11.1-1.amzn2023.0.1.aarch64

is not owned by any package と出たものは、dnf では更新されません。自分で更新を追いかけます。

言語ごとのパッケージ管理も確認します。

Command

pip3 list 2>/dev/null | head -5
npm ls -g --depth=0 2>/dev/null

また、パッケージが入れたファイルが書き換えられていないかは、rpm -V で確認できます。

Command

rpm -V openssl

何も出力されなければ、変更されたファイルはありません。設定ファイル(c が付く)の変更は正常ですが、実行ファイルやライブラリが変更されていたら、改ざんを疑います。

4. AL2023 のパッチ込みのバージョンを確認する#

rpm の %{VERSION}-%{RELEASE} を使うと、AL2023 のリビジョンまで含めたバージョンが表示されます。

Command

rpm -q openssl openssh-server

Output

openssl-3.0.8-1.amzn2023.0.18.aarch64
openssh-server-8.7p1-38.amzn2023.0.14.aarch64

バージョン表記の読み方#

openssl-3.0.8-1.amzn2023.0.18 を分けると、次のとおりです。

部分意味
3.0.8上流(OpenSSL プロジェクト)のバージョン
1パッケージのリリース番号
amzn2023AL2023 向けにビルドされたことを表す
0.18AL2023 での修正の通し番号。セキュリティ修正が入るたびに増える

dnf list の表示にある 1: は エポック で、バージョンの比較の優先順位を調整するための番号です。

バージョン番号だけで脆弱性は判断できない#

上流の修正が、バージョンを上げずに取り込まれる(バックポート)ことがあります。openssl 3.0.8 は上流では古いバージョンですが、amzn2023.0.18 のように末尾が進んでいれば、多くの修正が入っています。

そのため、php -v や openssl version の表示だけで判断してはいけません。changelog で CVE が修正されているかを確認します。

Command

rpm -q --changelog openssl | grep -m5 CVE-

Output

- Fix CVE-2026-2171: ...
- Fix CVE-2026-1895: ...

特定の CVE が修正済みかは、dnf でも調べられます。

Command

dnf updateinfo info --cve CVE-2026-109618

Output(例)

===============================================================================
  php8.4 security update
===============================================================================
  Update ID: ALAS2023-2026-1234
       Type: security
   Severity: Critical
     Issued: 2026-10-21
       CVEs: CVE-2026-109618
Description: ...

AL2023 の CVE 情報は、Amazon Linux Security Center(explore.alas.aws.amazon.com)でも確認できます。

5. 更新状況・サービス・ポート・ユーザー#

アップグレードできるパッケージを確認します。

Command

dnf check-update
echo "exit code: $?"

Output(抜粋)

cloud-init.noarch        23.4.4-1.amzn2023.0.5        amazonlinux
libxml2.aarch64          2.10.4-1.amzn2023.0.12       amazonlinux
exit code: 100

更新があると、終了コードが 100 になります。何もなければ 0 です。スクリプトで更新の有無を判断するときに使えます。

セキュリティ修正だけを見るには、updateinfo を使います。

Command

dnf updateinfo list security
dnf updateinfo summary

Output(抜粋)

ALAS2023-2026-1234 Critical/Sec. php8.4-cli-8.4.27-1.amzn2023.0.1.aarch64
ALAS2023-2026-1198 Important/Sec. libxml2-2.10.4-1.amzn2023.0.12.aarch64

Updates Information Summary: available
    2 Security notice(s)
        1 Critical Security notice(s)
        1 Important Security notice(s)

Critical や Important のものは、優先して当てます。ただし、これは今のリリースで見えている範囲の情報です。 より新しいリリースにある修正は、6 章の check-release-update で別に確認します。

動作中のサービスを確認します。

Command

systemctl list-units --type=service --state=running

Output(抜粋)

  UNIT                      LOAD   ACTIVE SUB     DESCRIPTION
  amazon-ssm-agent.service  loaded active running Amazon SSM Agent
  chronyd.service           loaded active running NTP client/server
  httpd.service             loaded active running The Apache HTTP Server
  php-fpm.service           loaded active running The PHP FastCGI Process Manager
  sshd.service              loaded active running OpenSSH server daemon

知らないサービスが動いていたら、何のためのものかを調べます。不要なら止めて、自動起動を無効にします。失敗しているサービスも確認します。

Command

systemctl --failed

待ち受けポートを確認します。

Command

sudo ss -tlnp

Output(抜粋)

State   Local Address:Port   Process
LISTEN  0.0.0.0:22           users:(("sshd",pid=1021,fd=3))
LISTEN  *:80                 users:(("httpd",pid=1534,fd=4))
LISTEN  127.0.0.1:9000       users:(("php-fpm",pid=1602,fd=8))

0.0.0.0 や * は、すべてのネットワークから受け付けることを表します。外部に公開する必要がないものは、127.0.0.1 に限定します。EC2 では、セキュリティグループ側で閉じられていても、OS 側の待ち受けも確認しておきます。

ログインできるユーザーを確認します。

Command

getent passwd | awk -F: '$7 !~ /(nologin|false)$/ {print $1, $7}'

Output

root /bin/bash
ec2-user /bin/bash

また、SELinux の状態も確認します。

Command

getenforce

Output

Permissive

AL2023 は、標準で SELinux が Permissive(ログに記録するだけで、拒否はしない)です。Enforcing にするかは、アプリへの影響を確認して決めます。

6. パッチ適用とバージョンアップ#

流れ#

sudo dnf check-release-update   新しいリリースがあるかを見る
  → dnf check-update / updateinfo  何が更新されるかを見る
  → dnf upgrade --assumeno         シミュレーションで確認する
  → sudo dnf upgrade               適用する
  → 再起動が必要かを確認する

AL2023 の特徴: リリースが固定されている#

AL2023 では、各インスタンスが 特定のリリース(releasever)のリポジトリ を見ています。インスタンスを起動した AMI のリリースがそのまま使われ、自動では新しいリリースに進みません。 これは、同じ手順を実行したときに、同じ結果になるようにするための仕組みです。

今のリリースと、新しいリリースがあるかを確認します。

Command

cat /etc/dnf/vars/releasever 2>/dev/null || rpm -q --qf '%{VERSION}\n' system-release
sudo dnf check-release-update

Output

2023.9.20261020
Update Information:
 Version 2023.10.20261105 available
 Run the following command to update to 2023.10.20261105:
   dnf upgrade --releasever=2023.10.20261105

(出力は説明用の例です。)新しいリリースがあるのに進めていないと、セキュリティ修正が入りません。 dnf upgrade だけでは、今のリリースの範囲内の更新しか入らないためです。

最新のリリースに進むには、--releasever を指定します。

Command

sudo dnf upgrade --releasever=latest

特定のリリースに合わせたいときは、リリースの番号を指定します(例: --releasever=2023.10.20261105)。複数のサーバーで同じリリースに揃えると、サーバー間のバージョンのずれを防げます。

適用する前にシミュレーションする#

実際には変更せずに、何が起きるかだけを見ます。

Command

sudo dnf upgrade --releasever=latest --assumeno

Output(抜粋)

Dependencies resolved.
===========================================================================
 Package           Arch      Version                    Repository    Size
===========================================================================
Installing:
 kernel            aarch64   6.1.163-186.300.amzn2023   amazonlinux   1.4 M
Upgrading:
 cloud-init        noarch    23.4.4-1.amzn2023.0.5      amazonlinux   1.1 M
 libxml2           aarch64   2.10.4-1.amzn2023.0.12     amazonlinux   708 k

Transaction Summary
===========================================================================
Install   1 Package
Upgrade  12 Packages

Operation aborted.

--assumeno は、確認の質問に「いいえ」と答えるので、内容を表示して中止します。見るのは次の点です。

  • Removing: 削除されるパッケージがないか。依存関係のために、必要なものが消えることがあります。
  • Installing: 新しく入るパッケージ。カーネルのように、更新が「新規インストール」として入るものがあります(次の「カーネルを更新する」を参照)。
  • Upgrading: アプリの動作に影響するもの(PHP、データベース、ミドルウェア)が含まれていないか。

適用する: dnf upgrade#

Command

sudo dnf upgrade --releasever=latest

途中で確認の質問が出ます。内容を確認して y を入力します。完了したら、履歴で確認します。

Command

dnf history info last

セキュリティ修正だけを当てたいときは、--security を付けます。

Command

sudo dnf upgrade --security --releasever=latest

緊急でない定期対応: 一括で最新に保つ#

緊急の脆弱性対応でなければ、特定のパッケージだけでなく、更新できるものを 一括で最新に保つ 選択肢があります。月 1 回などのメンテナンス時間を決めて、次の流れで行います。

1. sudo dnf check-release-update   新しいリリースがあるかを確認する
2. dnf check-update                更新されるものを確認する
3. dnf upgrade --assumeno          シミュレーションで、Install / Remove を確認する
4. 必要なら versionlock            止めたいものを除外する
5. sudo dnf upgrade                一括で適用する
6. 再起動が必要かを確認する          dnf needs-restarting
7. 動作を確認する                  サービスの状態、ログ、アプリの疎通

定期的に行うメリットは、更新の差分が小さく保たれ、1 回あたりの影響が読みやすくなることです。長く放置すると、更新が大きくなり、問題が起きたときに原因の切り分けも難しくなります。

AL2023 では、リリースを進めるタイミングを自分で決められる のが特徴です。検証用の環境で新しいリリースを先に試し、問題がなければ本番に同じリリースを適用する、という運用ができます。

種類方法
セキュリティ修正dnf-automatic で自動適用する(後述)か、定期のメンテナンスで --security を当てる
それ以外の更新定期のメンテナンス時間に、上の流れで一括適用する
緊急の脆弱性定期を待たず、7 章のように対象だけを先に更新する

本番環境では、いきなり一括適用せず、検証用の環境で同じ更新を先に試してから適用します。

どの運用でも、パッチが出たことに気づく仕組みが必要#

「定期的に当てる」「自動で当てる」「作り直す」のどれでも、パッチが出たことに気づく必要があります。AL2023 はリリースが固定されているので、気づかなければ、いつまでも古いリリースのまま です。

運用方針適用の方法気づく必要がある理由
定期的に当てる一括で dnf upgrade緊急のものは、定期を待たず先に対応するかを判断するため
自動で当てるdnf-automatic自動適用の対象外のものや、失敗したものに気づくため
作り直す最新の AMI で入れ替える気づかないと作り直すきっかけがなく、古いパッケージのまま動き続けるため

気づく手段の例は、次のとおりです。

  • AWS の情報: ALAS(Amazon Linux Security Advisory)を購読する。Amazon Linux Security Center で CVE を見る。
  • サーバー側の検知: dnf check-release-update と dnf updateinfo list security を定期的に実行する。
  • AWS のサービス: Amazon Inspector で脆弱性を検出する。Systems Manager の Patch Manager で、パッチの適用状況を管理する。
  • 作り直す運用: 最新の AMI の ID を SSM パラメータストア(/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64)から取得して、起動テンプレートに反映する。
  • ミドルウェアの情報: PHP のようにアプリの動作に直結するものは、公式のリリース情報を別に追う。

更新の前後で何が変わったかを記録しておく#

更新の作業は、あとから「何がどう変わったか」を説明できるようにしておくと、障害の調査や監査のときに役立ちます。更新の前にスナップショットを取り、実行ログを残し、更新後に差分を取る運用です。

1. 更新前にスナップショットを取る

mkdir -p ~/upgrade-log/$(date +%F) && cd ~/upgrade-log/$(date +%F)

rpm -qa --qf '%{NAME} %{VERSION}-%{RELEASE}\n' | sort > before.txt   # 全パッケージの版
dnf check-update > upgradable.txt                                    # 更新候補
sudo dnf upgrade --assumeno > simulate.txt 2>&1                      # 今回のシミュレーション
uname -r > kernel_before.txt                                         # 動いているカーネル
rpm -q system-release > release_before.txt                           # リリース
systemctl --failed > failed_before.txt                               # 失敗しているサービス

2. 更新の実行ログも残す

sudo dnf upgrade -y 2>&1 | tee upgrade.log

-y は確認を省略するので、simulate.txt で Removing の中身を確認してから実行します。

3. 更新後に差分を取る

rpm -qa --qf '%{NAME} %{VERSION}-%{RELEASE}\n' | sort > after.txt
diff before.txt after.txt > diff.txt     # 版が変わったものだけが出る
cat diff.txt

sudo dnf needs-restarting -r             # 再起動が必要かを確認する
sudo reboot
# 再起動後
uname -r > kernel_after.txt
systemctl --failed > failed_after.txt

diff.txt には、バージョンが変わったパッケージだけが、更新前(<)と更新後(>)の組で出ます。再起動のあとは、kernel_before.txt と kernel_after.txt を比べて、カーネルが新しくなったことを確認します。failed_before.txt と failed_after.txt を比べれば、更新で壊れたサービスにも気づけます。

dnf 自身も、dnf history で更新の履歴を残しています。ここで紹介した方法は、それに加えて「更新前の状態」と「更新後の差分」を、手元で見やすい形でまとめて残すものです。

特定のパッケージだけを更新する#

緊急の脆弱性対応などで、1 つだけ更新したいときは、パッケージ名を指定します。

Command

sudo dnf upgrade openssh-server

Output(抜粋)

Upgrading:
 openssh-server   aarch64   8.7p1-38.amzn2023.0.15   amazonlinux   457 k
Upgrading dependencies:
 openssh          aarch64   8.7p1-38.amzn2023.0.15   amazonlinux   340 k

Transaction Summary
Upgrade  2 Packages

dnf upgrade <名前> は、入っていないパッケージを新しくインストールしません(dnf install は入れます)。ただし、更新に必要な依存パッケージは、新しく入ることがあります。実行前に --assumeno でシミュレーションして、Installing と Removing の中身を確認します。

ソフトウェア単位で更新する具体的な流れは、7 章の PHP の例で詳しく見ます。

カーネルだけを更新する#

カーネルは、ほかのパッケージと更新のされ方が違います。カーネルは 古いものを残したまま、新しいものが追加で入ります(installonly)。通常は直近の 3 つが残ります。

Command

rpm -q kernel --last
uname -r

Output

kernel-6.1.163-186.300.amzn2023.aarch64   Mon 20 Oct 2026 10:12:03 AM UTC
kernel-6.1.158-180.294.amzn2023.aarch64   Mon 08 Sep 2026 02:09:41 AM UTC
6.1.158-180.294.amzn2023.aarch64

rpm -q kernel --last の先頭が、入っている最新のカーネルです。uname -r が動いているカーネルです。両者が違えば、新しいカーネルは入っているが、再起動していません。 再起動するまで、古いカーネルで動き続けます。

カーネルだけを更新します。

Command

sudo dnf upgrade kernel
sudo reboot
# 再起動後
uname -r

再起動の時間が取れないときは、カーネルを除外して、それ以外を先に当てられます。

Command

sudo dnf upgrade --exclude='kernel*'

AL2023 には、再起動なしでカーネルの脆弱性を修正する カーネルライブパッチ もあります。有効にすると、重大な脆弱性の一部が再起動なしで修正されます。ただし、すべての修正がライブパッチで配信されるわけではないので、定期的な再起動とカーネルの更新は必要です。

再起動が必要かを確認する#

パッケージを更新しても、動いているプロセスは古いライブラリやコードを使い続けます。再起動が必要かを確認します。

Command

sudo dnf needs-restarting -r
echo "exit code: $?"

Output

Core libraries or services have been updated since boot-up:
  * kernel
  * glibc

Reboot is required to fully utilize these updates.
exit code: 1

再起動が必要なときは、終了コードが 1 になります。必要なければ 0 です。needs-restarting が見つからないときは、sudo dnf install -y dnf-utils で入れます。

再起動までは不要でも、サービスの再起動が必要なものを確認できます。

Command

sudo dnf needs-restarting -s

Output

php-fpm.service
httpd.service
sshd.service

出力されたサービスは、古いライブラリを使ったまま動いています。順番に再起動します。

更新したくないパッケージを止める: versionlock#

特定のパッケージのバージョンを固定します。versionlock プラグインを使います。

Command

sudo dnf install -y python3-dnf-plugin-versionlock
sudo dnf versionlock add php8.4-cli
dnf versionlock list

Output

php8.4-cli-0:8.4.26-1.amzn2023.0.1.*

解除するときは、sudo dnf versionlock delete php8.4-cli です。

hold したパッケージは、セキュリティ修正も入りません。固定した理由と期限を、記録しておきます。一時的に除外するだけなら、--exclude を使います。

自動更新(dnf-automatic)を確認する#

AL2023 では、標準では自動更新が設定されていません。必要なら dnf-automatic を設定します。まず、入っているかと、動いているかを確認します。

Command

rpm -q dnf-automatic
systemctl list-timers 'dnf-automatic*'

Output

package dnf-automatic is not installed
0 timers listed.

自動更新を設定するときは、次のようにします。

Command

sudo dnf install -y dnf-automatic
sudo sed -i 's/^upgrade_type = .*/upgrade_type = security/; s/^apply_updates = .*/apply_updates = yes/' /etc/dnf/automatic.conf
sudo systemctl enable --now dnf-automatic.timer

upgrade_type = security で、セキュリティ修正だけを自動で適用します。apply_updates = yes で、確認なしに適用します。

自動適用には、Ubuntu の unattended-upgrades と同じ注意があります。

  • サービスの再起動: パッケージが更新されると、そのサービスが自動で再起動される場合があります。
  • カーネルは自動で再起動されない: 再起動するまで、古いカーネルで動き続けます。
  • リリースは進まない: dnf-automatic は、今のリリースの範囲内で更新します。新しいリリースの修正を入れるには、releasever を進める必要があります。
  • 失敗に気づく仕組み: メール通知(emit_via)や、ログの監視で、適用の失敗に気づけるようにします。

AL2023 では、更新を自動で行うかどうかよりも、リリースを進める運用を決めておくこと が重要です。

dnf の管理外のものも更新する#

/usr/local に置いたバイナリや、pip、npm で入れたものは、dnf upgrade では更新されません。

Command

terraform version
pip3 list --outdated 2>/dev/null | head -5

それぞれの方法で、自分で更新します。可能なら、dnf で管理できる形(リポジトリや RPM)に寄せると、更新を追いかけやすくなります。

元に戻す#

更新で問題が起きたときは、dnf の履歴から元に戻せます。

Command

dnf history list | head -4
sudo dnf history undo last

history undo は、その取引で入ったパッケージを、1 つ前のバージョンに戻します。古いバージョンがリポジトリに残っている必要があります。AL2023 は、リリースごとにリポジトリが固定されているので、以前のリリースのバージョンを取得できます。

ただし、カーネルやライブラリを戻すと、別の問題が起きることがあります。確実に戻せるように、更新の前に EBS のスナップショットか AMI を取っておきます。

AL2023 の中でリリースを上げる、別のバージョンに移行する#

同じ AL2023 の中では、--releasever を進めることが、リリースのアップグレードに当たります。Ubuntu の do-release-upgrade のような、OS の大きな更新ではありません。

OS のメジャーバージョンを上げる(Amazon Linux 2 から AL2023 に移行するなど)ときは、インプレースでの更新はできません。新しいバージョンのインスタンスを作り、アプリを移行します。 Amazon Linux 2 は 2026 年 6 月 30 日にサポートが終了しているので、利用中の場合は移行を急ぎます。AL2023 も、標準サポートが 2027 年 6 月 30 日、サポート全体が 2029 年 6 月 30 日に終わるので、次の移行の時期を、1 章の表で確認しておきます。

7. 事例: PHP2Shell に対応する#

ここまでの手順を、実際の脆弱性対応に当てはめてみます。題材は、2026 年 10 月に公開された PHP の脆弱性「PHP2Shell」です。

PHP2Shell の概要#

項目内容
CVECVE-2026-109618、CVE-2026-109619
内容PHP 本体のメモリ安全性の不具合。ログインなしで、リモートからコードを実行される
深刻度CVSS v4.0 で 9.2(Critical)
経緯10 月 20 日に、修正版が出る前に詳細がネットに流出。10 月 21 日に PHP が修正版を公開
上流の修正版PHP 8.5.12、8.4.27、8.3.36、8.2.35

CVE-2026-109619 はアップロードの進捗表示機能での解放後使用(use-after-free)、CVE-2026-109618 はメモリ不足が起きたときのメモリ破壊です。PHP は「設定変更だけでは完全には防げない」としていて、修正版への更新が唯一の確実な対策です。

インターネットに公開している PHP のサイトがあれば、すぐに対応が必要な種類の脆弱性です。この節では、AL2023 で php8.4 を使っている場合を例にします。

流れ#

1. PHP が入っているか、どこから入れたかを確認する
2. ALAS で、修正済みのバージョンを確認する
3. 修正版が届いているかを見る(リリースを進める必要があるか)
4. PHP のパッケージだけをシミュレーション → 更新する
5. changelog で CVE が修正されていることを確認する
6. PHP を読み込んでいるサービスを再起動する
7. dnf の管理外の PHP がないかを確認する

1. PHP が入っているかを確認する#

PHP に関係するパッケージを一覧にします。

Command

rpm -qa --qf '%{NAME}\t%{VERSION}-%{RELEASE}\t%{SOURCERPM}\n' | grep -i php

Output

php8.4-common   8.4.26-1.amzn2023.0.1   php8.4-8.4.26-1.amzn2023.0.1.src.rpm
php8.4-cli      8.4.26-1.amzn2023.0.1   php8.4-8.4.26-1.amzn2023.0.1.src.rpm
php8.4-fpm      8.4.26-1.amzn2023.0.1   php8.4-8.4.26-1.amzn2023.0.1.src.rpm
php8.4-opcache  8.4.26-1.amzn2023.0.1   php8.4-8.4.26-1.amzn2023.0.1.src.rpm

3 列目の ソース RPM は、そのパッケージの元になったソースです。php8.4-cli、php8.4-fpm のように名前が違っても、同じソース RPM(php8.4-...src.rpm)から作られていれば、同じ脆弱性の影響を受けます。名前の前方一致ではなく、ソース RPM で対象を特定します。

PHP がどう動いているかも確認します。

Command

systemctl list-units 'php*' 'httpd*' 'nginx*'

CLI だけの使用か、PHP-FPM や Apache と組み合わせた公開サービスかで、影響と緊急度が変わります。

2. 修正済みのバージョンを確認する#

AL2023 の修正は、Amazon Linux Security Center(explore.alas.aws.amazon.com/CVE-2026-109618.html)か、dnf で確認します。

Command

dnf updateinfo info --cve CVE-2026-109618 CVE-2026-109619

Output(例)

  Update ID: ALAS2023-2026-1234
       Type: security
   Severity: Critical
     Issued: 2026-10-21
       CVEs: CVE-2026-109618, CVE-2026-109619
Description: Package updates are available for Amazon Linux 2023 that fix the following vulnerabilities: ...

バージョン番号が上流の修正版(8.4.27)以上であることだけでなく、ALAS に載っているパッケージのバージョン と比べます。AL2023 では、バージョン番号が同じでも、リビジョンの違いで修正の有無が分かれることがあります。

3. 修正版が届いているかを見る#

修正版が、今のリリースで見えているかを確認します。

Command

dnf list --upgrades 'php8.4*'
sudo dnf check-release-update

Output

Available Upgrades
php8.4-cli.aarch64     8.4.27-1.amzn2023.0.1     amazonlinux
php8.4-common.aarch64  8.4.27-1.amzn2023.0.1     amazonlinux
...

何も表示されなくても、修正版がないとは限りません。 AL2023 では、修正が 新しいリリース にだけある場合があります。check-release-update で新しいリリースが出ていれば、それを指定して確認します。

Command

dnf list --upgrades --releasever=latest 'php8.4*'

4. PHP のパッケージだけを更新する#

ソース RPM を使って、対象のパッケージ名を取り出します。

Command

PKGS=$(rpm -qa --qf '%{NAME} %{SOURCERPM}\n' | awk '$2 ~ /^php8\.4-[0-9]/ { print $1 }')
echo $PKGS

Output

php8.4-common php8.4-cli php8.4-fpm php8.4-opcache

rpm -qa --qf でパッケージ名とソース RPM を出し、awk でソース RPM が php8.4- に続いて数字(バージョン)で始まるものだけを選びます。echo $PKGS は、クォートしないことで、改行をスペースに変えて 1 行で表示します。

まずシミュレーションで、影響を確認します。

Command

sudo dnf upgrade --releasever=latest --assumeno $PKGS

Upgrading に PHP のパッケージだけがあり、Removing がないことを確認してから、実行します。

Command

sudo dnf upgrade --releasever=latest $PKGS

修正版が今のリリースにすでにあるなら、--releasever=latest は不要です。--releasever を付けると、PHP 以外の依存パッケージも新しいリリースから入る場合があるので、シミュレーションで確認します。

5. 修正されたことを確認する#

バージョンが上がったことを確認します。

Command

rpm -q $PKGS

Output

php8.4-common-8.4.27-1.amzn2023.0.1.aarch64
php8.4-cli-8.4.27-1.amzn2023.0.1.aarch64
php8.4-fpm-8.4.27-1.amzn2023.0.1.aarch64
php8.4-opcache-8.4.27-1.amzn2023.0.1.aarch64

全パッケージが同じバージョンに揃っていることを確認します。一部だけ古いものが残っていると、取りこぼしです。

修正が入っていることを、changelog で確認します。

Command

rpm -q --changelog php8.4-common | grep -E 'CVE-2026-10961[89]'

Output

- Fix CVE-2026-109618
- Fix CVE-2026-109619

php -v の表示では、判断しないでください。バックポートされた修正は、上流のバージョン番号に出ません。

6. PHP を読み込んでいるサービスを再起動する#

パッケージを更新しても、動いている PHP-FPM や Apache は、古いコードのまま動き続けます。再起動が必要なサービスを確認します。

Command

sudo dnf needs-restarting -s | grep -E 'php|httpd|nginx'

Output

php-fpm.service
httpd.service

出たサービスを再起動します。先に設定の文法を確認しておくと、再起動で止まる事故を防げます。

Command

sudo php-fpm -t
sudo apachectl configtest
sudo systemctl restart php-fpm httpd
systemctl status php-fpm httpd --no-pager | grep -E 'Active|since'

since の時刻が今になっていれば、再起動されています。もう一度 sudo dnf needs-restarting -s を実行して、PHP のサービスが出ないことを確認します。

7. dnf の管理外の PHP がないかを確認する#

dnf で更新しても、ほかの方法で入れた PHP は更新されません。

Command

which -a php
rpm -qf $(which php)

is not owned by any package と出る PHP は、dnf の管理外です。ソースからビルドしたもの、/opt に置いたもの、コンテナの中のものがないかを確認します。

Command

sudo docker ps --format '{{.Names}}\t{{.Image}}' 2>/dev/null | grep -i php

ホストの PHP を更新しても、コンテナの中の PHP は古いままです。修正版のイメージに変えて、作り直します。

更新前後の確認観点のまとめ#

ここまでの確認を、更新の前と後に分けて整理します。

時点観点確認することコマンド
更新前入っているもの対象のパッケージと、更新前のバージョンを控えるrpm -qa --qf '%{NAME} %{VERSION}-%{RELEASE}\n' | grep php8.4 > before.txt
更新前動き方CLI、PHP-FPM、Apache のどれで動いているかsystemctl list-units 'php*' 'httpd*'
更新前修正版の有無今のリリースで見えているか、リリースを進める必要があるかdnf list --upgrades 'php8.4*'、dnf check-release-update
更新後全部上がった更新前の控えと比べて、取りこぼしがないrpm -qa --qf '%{NAME} %{VERSION}-%{RELEASE}\n' | grep php8.4 | diff before.txt -
更新後修正が入っている対象の CVE が changelog にあるrpm -q --changelog php8.4-common | grep CVE-
更新後設定が読める再起動の前に、文法エラーがないphp-fpm -t、apachectl configtest
更新後プロセスが新しい動いているプロセスが再起動されているsudo dnf needs-restarting -s
更新後機能が保たれている必要な拡張モジュールが読み込まれているphp -m を更新前と比べる
更新後アプリが動く実際のリクエストが成功し、ログにエラーが増えていないヘルスチェック用の URL への curl -I、journalctl -u php-fpm --since "10 min ago"

パッケージのバージョンが上がっても、サービスが再起動されていなければ、メモリ上では古いコードが動き続けます。バージョンの確認だけで終わらせず、再起動とアプリの動作確認までを対応の完了とします。

すぐに更新できないとき#

検証が間に合わないなどの理由ですぐに更新できない場合でも、「何もしない」は選択肢になりません。PHP は設定変更だけでは完全に防げないとしています。外部に公開しているサイトなら、一時的に公開を止める、セキュリティグループやWAFでアクセス元を絞る、といった手当てをしてから、検証と更新を進めます。

参考#

まとめ#

  • dnf list installed は 取得元・バージョン が分かる。スクリプトで処理や比較をするなら、出力が安定している rpm -qa --qf ... を使う
  • dnf repoquery --userinstalled の「手動」は、dnf の管理内での話。セキュリティ上の盲点になりやすいのは、dnf の管理外で入れたもの(ソースビルド、言語別のパッケージ管理、/usr/local のバイナリ)。rpm -qf で確認する
  • バージョン番号だけで判断せず、changelog と dnf updateinfo で修正状況を確認する
  • AL2023 はリリースが固定されている。 dnf upgrade だけでは、新しいリリースの修正が入らない。dnf check-release-update で新しいリリースを確認し、--releasever で進める
  • パッチは check-release-update → シミュレーション(--assumeno)→ dnf upgrade → 再起動の要否確認(needs-restarting) の順で当てる。Removing が出たら立ち止まる
  • 特定のパッケージだけを更新するときは dnf upgrade <名前>。カーネルは古いものが残ったまま追加で入るので、再起動して uname -r で切り替わりを確認する
  • 脆弱性対応は ソース RPM で対象を特定 → ALAS の修正版と比較 → 対象だけ更新 → changelog で確認 → サービスを再起動 の順で行う。php -v のような上流のバージョン表示では判断しない
  • versionlock したパッケージと dnf の管理外のものは、自動では更新されない。自分で追いかける
  • どの運用でも、パッチが出たことに気づく仕組み(ALAS、Inspector、Patch Manager、定期の確認)が必要。更新の前には EBS のスナップショットか AMI を取っておく