
Amazon Linux 2023 の公式 SRPM から PHP 8.2.35 を CodeBuild でビルドしてみた
はじめに
梶原@福岡オフィスです。
PHP の重大な脆弱性 2 件が発表され、深夜対応してました。
公式のパッチが出るまでの待ち時間で、なんとかできることを模索しつつ、ないなら作ればいいんじゃね?
ということで試行錯誤した内容を共有します。
2026 年 10 月 21 日(日本時間)に、PHP の重大な脆弱性 2 件(CVE-2026-109618・CVE-2026-109619、CVSS v4.0 9.2)の修正版が公開されました。認証なしでリモートコード実行ができるおそれがあります。
8.2 系の修正版は 8.2.35 です。Amazon Linux 2023(以下 AL2023)の php8.2 は、2026 年 10 月 22 日 7 時の時点で、ALAS の CVE のページでは 2 件とも Pending Fix です。
- https://explore.alas.aws.amazon.com/CVE-2026-109618.html
- https://explore.alas.aws.amazon.com/CVE-2026-109619.html
今回は、AL2023 公式の php8.2 の SRPM を取り出し、ソースだけを 8.2.35 に差し替えて、AWS CodeBuild でビルドしました。手元の PC には負荷をかけずに済み、ビルドは約 7 分、動作確認は数分で終わりました。
調査・ビルド・動作確認は、生成 AI(Claude Code)に指示して進めました。
この記事では、その手順を紹介します。
方針
あくまで、公式パッケージを待ちつつ、動作確認などやれるものを先にやるために進めています。
公式パッケージがでたときに、変に邪魔しないよう考慮しています。
- AL2023 公式の SRPM(今回は
php8.2-8.2.34-1.amzn2023.0.1)を使う。設定ファイルの置き場所やパッケージの分け方が今と変わらない - 差し替えるのはソースの tarball だけにする。spec に入っているパッチ(Fedora の php.spec と同じ 10 種類)はそのまま当てる
- リリース番号を
0.cm1にする。今の8.2.34-1より新しく、公式の8.2.35-1より古いので、公式版が 8.2.35 で出たら自動更新で置き換わる - ビルドは CodeBuild で、素の AL2023 イメージ(
public.ecr.aws/amazonlinux/amazonlinux:2023)を使う。標準イメージには別の PHP が入っていて、確認のときにそちらが動いてしまうため
生成AIとやってみた
生成AIに上記方針でやれ!って言いました。
1. CodeBuild の準備
成果物を置く S3 バケットと、CodeBuild 用の IAM ロールを作ります。ロールには、CloudWatch Logs への書き込みと、このバケットの読み書きだけを許可します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
"Resource": "arn:aws:logs:ap-northeast-1:<アカウント ID>:log-group:/aws/codebuild/php-build*"
},
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:GetBucketLocation"],
"Resource": ["arn:aws:s3:::<バケット名>", "arn:aws:s3:::<バケット名>/*"]
}
]
}
プロジェクト名は php-build で、ソースなし(NO_SOURCE)で作り、buildspec をプロジェクトに直接書きました。
イメージは public.ecr.aws/amazonlinux/amazonlinux:2023、コンピューティングタイプは BUILD_GENERAL1_LARGE です。
2. buildspec
version: 0.2
env:
shell: bash
variables:
# 元にする AL2023 公式の SRPM
SRPM: php8.2-8.2.34-1.amzn2023.0.1
# 差し替える PHP の版
NEWVER: 8.2.35
# php.net が公開している php-8.2.35.tar.xz の SHA256
SHA256: 5737b98601fe5ab1b8c5db0c82ed3158acb9283ed3081ffe2faffb9ac81455e6
phases:
install:
commands:
# ビルドに使うツールを入れる(gnupg2 は署名の検証用。gnupg2-minimal と入れ替えるため --allowerasing)
- dnf install -y --allowerasing rpm-build dnf-plugins-core xz wget gnupg2
# パッケージ名の末尾に付く dist タグ(.amzn2023)をログに出す
- echo "dist=$(rpm --eval '%{?dist}')"
pre_build:
commands:
# 公式の SRPM をダウンロードする
- cd /tmp && dnf download --source "$SRPM"
# SRPM を ~/rpmbuild に展開する(spec は SPECS、ソースとパッチは SOURCES)
- rpm -ivh /tmp/${SRPM}.src.rpm
# spec のパスをファイルに控え、後のコマンドで読み出す
- SPEC=$(ls ~/rpmbuild/SPECS/*.spec | head -1); echo "$SPEC" > /tmp/specpath
# 新しいソースを php.net から取り、SHA256 を照合する
- cd ~/rpmbuild/SOURCES && wget -q https://www.php.net/distributions/php-${NEWVER}.tar.xz && echo "${SHA256} php-${NEWVER}.tar.xz" | sha256sum -c -
# 署名ファイルを取る(spec の %gpgverify が検証に使う)
- cd ~/rpmbuild/SOURCES && wget -q https://www.php.net/distributions/php-${NEWVER}.tar.xz.asc
# spec の版(%global upver)を 8.2.35 に、Release を 0.cm1 に書き換える
- SPEC=$(cat /tmp/specpath); sed -i -E "s/^(%global[[:space:]]+upver[[:space:]]+)8\.2\.34/\1${NEWVER}/; s/^(Release:[[:space:]]*).*/\10.cm1%{?dist}/" "$SPEC"
# spec が必要とするビルド用パッケージを入れる
- SPEC=$(cat /tmp/specpath); dnf builddep -y "$SPEC"
# ソースの展開とパッチ当てだけを行い、パッチが当たるかを先に確かめる
- SPEC=$(cat /tmp/specpath); rpmbuild -bp "$SPEC" > /tmp/prep.log 2>&1 || { tail -80 /tmp/prep.log; exit 1; }
# 署名の検証結果をログに出す
- echo "PREP OK"; grep -i -E "gpgv|signature" /tmp/prep.log
build:
commands:
# バイナリの RPM をビルドする(%check の make test は飛ばす)
- SPEC=$(cat /tmp/specpath); rpmbuild -bb --nocheck "$SPEC" > /tmp/build.log 2>&1 || { tail -120 /tmp/build.log; exit 1; }
post_build:
commands:
# 入れ替えたい 5 パッケージだけを集め、SHA256SUMS を作る
- mkdir -p /tmp/out && cp ~/rpmbuild/RPMS/x86_64/php8.2-{cli,common,fpm,mbstring,xml}-${NEWVER}-*.rpm /tmp/out/ && cd /tmp/out && sha256sum *.rpm | tee SHA256SUMS
# /tmp/out の中身をすべて S3 に置く
artifacts:
base-directory: /tmp/out
files:
- '*'
ポイントは次のとおりです。
SHA256は php.net の JSON(https://www.php.net/releases/index.php?json&version=8.2)で公開されている値です。ビルドの中で照合します- spec の版は
Version:ではなく%global upverで決まっていました。Version: %{upver}%{?rcver:~%{rcver}}という書き方です - spec の
%gpgverifyで署名を検証するので、.ascも SOURCES に置き、gnupg2を入れます。素のイメージにあるgnupg2-minimalとぶつかるため、--allowerasingを付けます - 本ビルドの前に
rpmbuild -bp(ソースの展開とパッチ当てだけ)を挟みました。spec のパッチが新しいソースに当たらなければ、ここで早く止まります。今回はすべて当たりました %check(make test)は--nocheckで飛ばしました。テストの結果は、次の「make test の結果」で別に確かめています- 取り出すのは、入れ替えたいパッケージ(cli・common・fpm・mbstring・xml)だけにしました
ビルドは約 7 分で終わりました。署名の検証は、ログに次のように出ます。
gpgv: Signature made Mon Oct 19 07:34:32 2026 UTC
gpgv: using RSA key E60913E4DF209907D8E30D96659A97C9CF2A795A
gpgv: Good signature from "Sergey Panteleev <sergey@php.net>"
できた RPM は次の 5 つです。
php8.2-cli-8.2.35-0.cm1.amzn2023.x86_64.rpm
php8.2-common-8.2.35-0.cm1.amzn2023.x86_64.rpm
php8.2-fpm-8.2.35-0.cm1.amzn2023.x86_64.rpm
php8.2-mbstring-8.2.35-0.cm1.amzn2023.x86_64.rpm
php8.2-xml-8.2.35-0.cm1.amzn2023.x86_64.rpm
3. make test の結果
あとから、同じ buildspec で --nocheck を外して %check を流しました。テストは約 1 分で終わり、ビルド全体の時間は --nocheck のときとほぼ同じでした。
Number of tests : 18784 10854
Tests skipped : 7930 ( 42.2%) --------
Tests failed : 1 ( 0.0%) ( 0.0%)
Expected fail : 6 ( 0.0%) ( 0.1%)
Tests passed : 10847 ( 57.7%) ( 99.9%)
失敗した 1 件は ext/pcre/tests/gh11956.phpt(PCRE の JIT を使う正規表現のテスト)です。
差し替えをしない公式の 8.2.34 でも、同じテストが同じ結果で失敗しました。8.2.35 で増えた失敗はありません。
spec の %check は、テストが失敗してもビルドを止めません(exit 1 がコメントアウトされています)。テストを流すときは、ビルドの成否ではなくログの TEST RESULT SUMMARY を見てください。
4. 素の AL2023 で入れ替えを確認する
同じ CodeBuild プロジェクトで、別の buildspec を渡して確認しました(start-build の --buildspec-override)。8.2.34 と nginx を入れてから自作の RPM に入れ替え、nginx と php-fpm 経由のリクエストまで通します。素のイメージには AWS CLI がないので、RPM は aws s3 presign で作った署名付き URL から curl で取りました。
V=8.2.34-1.amzn2023.0.1
dnf install -y php8.2-cli-$V php8.2-common-$V php8.2-fpm-$V php8.2-mbstring-$V php8.2-xml-$V nginx
mkdir -p /tmp/rpms && cd /tmp/rpms
curl -sSf -o php8.2-fpm-8.2.35-0.cm1.amzn2023.x86_64.rpm '<署名付き URL>' # 5 個と SHA256SUMS
sha256sum -c SHA256SUMS
md5sum /etc/php.ini /etc/php-fpm.d/www.conf > /tmp/conf-before.md5
dnf -y install /tmp/rpms/*.rpm
/usr/bin/php -v
md5sum -c /tmp/conf-before.md5
mkdir -p /run/php-fpm && /usr/sbin/php-fpm -D
echo '<?php echo "fpm ", PHP_VERSION, " ", php_sapi_name();' > /usr/share/nginx/html/v.php
echo '<?php echo count($_FILES), " ", $_FILES["f"]["size"] ?? 0;' > /usr/share/nginx/html/u.php
head -c 100000 /dev/urandom > /tmp/up.bin
/usr/sbin/nginx
curl -s http://127.0.0.1/v.php
curl -s -F f=@/tmp/up.bin http://127.0.0.1/u.php # multipart の POST
dnf -y history undo last # 元に戻せるか
結果です。
== before
PHP 8.2.34 (cli) (built: Sep 22 2026 08:44:13) (NTS gcc x86_64)
== after
PHP 8.2.35 (cli) (built: Oct 19 2026 07:29:52) (NTS gcc x86_64)
== config unchanged
/etc/php.ini: OK
/etc/php-fpm.d/www.conf: OK
== http via nginx+fpm
fpm 8.2.35 fpm-fcgi [200]
== upload (multipart POST)
1 100000 [200]
== rollback
PHP 8.2.34 (cli) (built: Sep 22 2026 08:44:13) (NTS gcc x86_64)
5. サーバーへの入れ方
dnf upgrade は公式リポジトリしか見ないので、ファイルを指定して dnf install します。
sha256sum -c SHA256SUMS
sudo dnf -y install ./php8.2-*-8.2.35-0.cm1.amzn2023.x86_64.rpm
sudo systemctl restart php-fpm
php -v
rpm -q php8.2-fpm の結果に cm1 が付いていれば、自作ビルドの版です。戻すときは sudo dnf history undo last です。
自分の環境に合わせて変えるところ
PHPのバージョンや、OS など、自分の環境に合わせて変更してください。生成AIに指示を入れれば大体対応できるかと思います。
| 変えたいこと | 変える場所 |
|---|---|
| PHP のマイナー版(8.3・8.4 など) | SRPM・NEWVER・SHA256 に加え、sed の 8\.2\.34 と post_build の php8.2- も合わせる。SRPM の版は dnf list --showduplicates php8.3、SHA256 は php.net の JSON(version=8.3)で調べる |
| 取り出すパッケージ | post_build の {cli,common,fpm,mbstring,xml}。サーバーで rpm -qa 'php8.2*' を見て、入っているものを並べる |
| リリース番号 | cm1 は自分の識別子に変えてよい。先頭の 0. は残す |
こちらで試したのは 8.2 系・x86_64 だけです。
そのあと、いくつか、バージョン違いで作成をしましたが、特に問題なさそうでした。
注意点
- 公式の修正が 8.2.35 ではなく、8.2.34 に修正を取り込んだ版(例:
8.2.34-2.amzn2023)で出た場合は、自作の8.2.35-0.cm1のほうが新しい扱いになり、自動では置き換わりません。dnf distro-sync 'php8.2*'で公式リポジトリの版に戻します - 確かめたのは PHP 本体のテストと簡単な動作確認だけです。本番の前にステージングでアプリの動作を確認することを強くお勧めします
- php.net は「完全な回避策はなく、更新だけが安全」としています。
まとめ
AL2023 公式の SRPM を元に、ソースだけを差し替えて CodeBuild でビルドし、修正版の PHP を用意できました。
CodeBuild を用いることで手元の PC を使わずに済み、ビルドは約 7 分、動作確認は数分でした。
同じやり方は、今後似たような脆弱性や、ほかの RPM 系ディストリビューション、PHP 以外のパッケージにも使えると考えています。
その場合も、動作確認は本番と同じ素の OS イメージで行い、リリース番号は公式版より小さくして、公式パッケージの更新をなるべく邪魔せずに先行することができるかと思います。











