PHP2Shell対応でphp83をportsから更新した(FreeBSD)
Updating php83 from ports for PHP2Shell (FreeBSD)
事の発端
2026-10-21に、PHP本体の脆弱性が2件公開されました。通称PHP2Shellと呼ばれているみたいです。修正版も同時にリリースされています。
私の環境では、FreeBSDの公式pkg(quarterly)のphp83 8.3.35をphp-fpmで動かしていて、前段のApacheで複数のサイトを公開しています。
pkgは8.3.35のまま更新されず、いつ追いつくのかも分かりません・・・認証不要のリモートコード実行をWebに公開した状態で、pkgの更新を待つのが個人的に怖かったので、今回応急処置として、portsからソースビルドして更新することにしました。
途中でlldのエラーでビルドが失敗したりとちょっとハマったので、備忘録として残しておきます。
誰かの参考になれば幸いです。
PHP2Shellとは
- CVE-2026-109618(OOM時の破損)とCVE-2026-109619(解放後に残るグローバル状態)の2件
- どちらもCVSS v4.0で9.2、認証不要のリモートコード実行
- 影響するSAPIは、PHP-FPM、Apache mod_php、php-cgi、FrankenPHP、LiteSpeedなど、Webリクエストを処理するもの
- 修正版は 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35
- Wizの記述では、CVE-2026-109618はupload-progressのunserializer、CVE-2026-109619はOPcacheのtype confusionが関係しているとのこと
- PHP 8.1以前は本家の通常サポート外(7.4 / 8.0 / 8.1向けにソースのバックポートが別途公開されています)
悪用状況は情報源によって差があります。今のところ、侵害の確認は報告されておらず、Cisco PSIRTは悪用を把握していないとしていました。一方でCISAは、即時の更新を強く求めているようです。
作業環境
- FreeBSD 14.5-RELEASE-p3 amd64
- pkgリポジトリ FreeBSD:14:amd64/quarterly
- PHP 8.3.35
- php-fpm(前段はApache、複数サイトを公開)
- インストール済み拡張: curl, gd, mbstring, mysqli, opcache, pdo, pdo_mysql, session, xml, zip
- PECLなどは入っていない
- ビルドオプション(更新前): CGI / CLI / DTRACE / EMBED / FPM / IPV6 / LINKTHR / MYSQLND / PCRE = on、DEBUG / NOASLR / PHPDBG / ZTS = off
FreeBSDでの扱い
前提として、PHPはFreeBSDのbaseには含まれず、Ports / pkg(lang/php8x)で配布されています。そのため、FreeBSD-SAは出ません。
脆弱性情報はVuXML(pkg audit)で扱われますが、私が確認した10/22 朝8時の時点では、PHP2Shellに該当するエントリは見当たりませんでした。
pkg auditだけに頼っていると気づけないので、注意が必要です。
作業開始時点(10/22 8:30)のportsの状況は次のとおりでした。
- php85: 修正版は8.5.12。portsは更新済み(10/21 13:40 UTC)、pkgは8.5.11
- php84: 修正版は8.4.27。portsは8.4.26_1のまま未更新、pkgは8.4.26
- php83: 修正版は8.3.36。portsは更新済み(10/21 13:39 UTC)、pkgは8.3.35
- php82: 修正版は8.2.35。portsは更新済み(10/21 13:39 UTC)、pkgは8.2.34
補足です。
- php81は2025-12-31にSunset(portsから削除)済み
- php82はdeprecated(EOL 2026-12-31)ですが、今回の修正版は出ている
- デフォルトのPHPは2026-09-28に8.4から8.5に変更された(UPDATING)
やったこと
- pkgを待たず、portsからビルドする
- 公式pkg(quarterly)は8.3.35のままで、更新時期が不明だった
- Webに公開していて、認証不要のRCEなので、待つリスクのほうが大きいと判断した
- portsはmainではなく、2026Q4ブランチを使う
- mainはquarterlyのpkgより新しい依存を要求することがある
- quarterlyブランチなら、今入っているパッケージと整合する(php83-8.3.36_1を確認)
- 拡張も同じバージョンに揃える
- 特にopcacheとsessionは更新必須とした
実行手順
事前確認
まず、今の状態とリポジトリ側の状態を確認します。
php -v # 8.3.35 を確認
pkg info -x php8
pkg update
pkg rquery '%n-%v' php83 php83-opcache # リポジトリは 8.3.35 のまま
pkg -vv | grep -E 'FreeBSD:|url' # quarterly を使用
pkg query -g '%o' 'php83-*' # 拡張の一覧
pkg query '%o %n-%v' | grep -Ei 'php|pecl' # PECL 系はなしBashportsツリーをquarterlyブランチに切り替え
git -C /usr/ports fetch --depth 1 origin 2026Q4
git -C /usr/ports checkout 2026Q4
make -C /usr/ports/lang/php83 -V PKGNAME # php83-8.3.36_1とでたらOK
pkg info -f php83 | grep -A15 -i options # 現行pkgのオプション
make -C /usr/ports/lang/php83 showconfig # portsのオプション確認Bashmake -V PKGNAME で期待したバージョンが出るかどうかは、必ず確認するようにしましょう。
ビルドと入れ替え
reinstall は先にdeinstallしてから入れ直す動きなので、ビルドに失敗するとPHP自体が消えてしまいます。そのため、先に clean build でビルドだけを済ませて、成功してからインストールしています。
make -C /usr/ports/lang/php83 install-missing-packages
make -C /usr/ports/lang/php83 config # DTRACE のチェックを外す
make -C /usr/ports/lang/php83 clean build # ビルド
make -C /usr/ports/lang/php83 reinstall clean # 再インストール
# 拡張パッケージも同様に
for o in $(pkg query -g '%o' 'php83-*'); do
make -C /usr/ports/$o clean build
done
for o in $(pkg query -g '%o' 'php83-*'); do
make -C /usr/ports/$o reinstall clean
doneBash起動前の確認と再起動
再起動する前に、設定のテストをしておきます。
$ php -v
PHP 8.3.36 (cli) (built: Oct 22 2026 09:34:41) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.36, Copyright (c) Zend Technologies
with Zend OPcache v8.3.36, Copyright (c), by Zend Technologies
$ php -m
[PHP Modules]
Core
curl
.
.
.
xml
Zend OPcache
zip
[Zend Modules]
Zend OPcache
$ sudo php-fpm -t
[22-Oct-2026 11:59:18] NOTICE: configuration file /usr/local/etc/php-fpm.conf test is successful
$ sudo service php_fpm restartBashハマったこと
ビルドがlldのエラーで失敗した
ld.lld: error: Zend/.libs/zend_dtrace.d.o requires an executable stack, but -z execstack is not specifiedBashDTRACEオプションが生成するオブジェクトを、lldが拒否していると見られます。ただしこれは推測で、同一の報告は確認できていません。
make config でDTRACEを外してビルドしたところ、成功しました。
-z execstack を指定する回避策もありそうですが、スタックが実行可能になって堅牢性が下がるので、使いませんでした。
なお、ログに出ていた MAKE_JOBS_UNSAFE=yes のヒントは汎用メッセージで、今回の原因とは無関係でした。
以下作業終了後の状態です。
php -v(CLI): PHP 8.3.36(built: Oct 22 2026 09:34:41)、OPcache 8.3.36php-fpm -v: PHP 8.3.36(fpm-fcgi)、OPcache 8.3.36php-fpm -t: test is successful- php-fpm: 起動確認済
- ビルドオプション: DTRACE=off
/usr/local/etc/php/ にある ext-20-filter.ini と ext-20-phar.ini は、どのパッケージにも属さない古いファイルでした。php -v に警告は出ていないので、放置で問題なさそうです。
脆弱な状態で公開していた期間は、おおよそ10/21夜の修正版公開から、10/22朝の更新完了までです。
修正後の確認事項
侵害の有無の確認
修正版の公開から更新完了までは脆弱な状態だったので、念のため確認します。
find /usr/local/www/apache24/data -name '*.php' -mtime -3 -lsBash更新した覚えのない場所のファイルや、uploads配下の .php がないかを見ます。今のところは問題ないようですが、Apacheのアクセスログで、身に覚えのないPOSTの急増がないかも確認する予定です。
新しいハードメモリ上限
今回の修正で新しいハードメモリ上限が加わり、到達するとプロセスが終了して、shutdownハンドラが実行されないとのことです。memory_limit と post_max_size が、アプリの要件に合っているかを見直そうと思います。
まとめ
やったこと自体は、portsを2026Q4ブランチに切り替えて、DTRACEを外してphp83と拡張を入れ直しただけです。
また、pkg auditに出ない段階でも深刻な脆弱性が公開されることがある、というのも改めて実感しました。VuXMLを待たずに、本家の情報とportsの更新状況を直接見に行く必要があります。
make reinstallは、先にdeinstallするので、ビルドに失敗すると(今回の場合はphpが)消えてしまうので、先にclean buildでビルドを済ませてからやるのが安全かと思います。
また、ZFS環境なら作業前にsnapshotを取っておけば色々あっても安心です。
今回のようなアップグレードの場合、PHPのコアだけではなく、拡張(opcacheやsession)も同じバージョンに揃える必要があるので、環境ごとに確認をしましょう。
今後は、memory_limitまわりの見直しが残っているので、ぼちぼちやっていこうと思います。
参考にした記事
- Wiz: PHP2Shell
- PHP2Shell(Wikipedia)
- Patchstack: PHP vulnerable to critical RCE
- Qualys: PHP2Shell
- Cisco Security Advisory: PHP October 2026
- The Hacker News: PHP Issues Emergency Patches for Two Critical PHP2Shell RCE Flaws
- FreshPorts: lang/php83
- FreshPorts: lang/php85
- FreeBSD VuXML
おわり