php

What does it do?

This repository holds the packaging for the Docker Official Image for PHP, a Docker image. [1a][1b] It is the Git repository for that image and directs readers to the Docker Hub page for how to use it. [2]

Activity, over time

Daily observations from the public event archive.

Attention

Daily stars & forks

Loading attention chart

Star accumulation

Cumulative stars

Loading star accumulation chart

Pull requests

Daily opens & merges

Loading pull requests chart

Conversations

Daily issues & comments

Loading conversations chart

Community

Daily accounts & reviews

Loading community chart

Releases

Daily releases

Loading releases chart

Mentions

103posts · 30d
Nov 30 posts
  1. Qiita · · @softbase

    【応急処置】PHP 7.4 のまま CVE-2026-109618 / 109619(RCE)を塞ぐ Docker イメージを公開しました はじめに 2026-10-21、PHP プロジェクトが 認証なしでリモートコード実行(RCE)が可能な脆弱性を 2 件 公表しました(php.net のアナウンス)。 - CVE-2026-109618(GHSA-w8hw-w9fx-j79w): メモリ不足(OOM)の処理が、内部のリクエストデータの初期化途中で PHP を中断させ、壊れたデータがクリーンアップ時に正しいデータとして扱われる - CVE-2026-109619(GHSA-6wmf-4rv5-p3rp): 解放済みのメモリを指すリクエスト用の内部状態が残り、同じワーカーが処理する次のリクエストでそれが使われる 影響を受けるのは、Web リクエストを処理するすべての PHP(PHP-FPM、Apache mod_php、php-cgi など)です。advisory は mod_php のリスクが最も高い としており、アプリケーションのコードが動く前に攻撃が成立する実証コードもあるとしています。 修正版が出たのは PHP 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 だけです。PHP 7.4 は EOL なので修正版は出ません。ただ、深刻度を考慮して、PHP セキュリティチームが 7.4 / 8.0 / 8.1 向けに 最小限のソース backport を公開しています。 一方で、Docker の公式イメージ php:7.4-* が再ビルドされることはありません。FROM php:7.4-apache のまま運用しているシステムは、何もしなければ脆弱なまま です。 そこで、この backport を当てて再ビルドした php:7.4-* 互換のイメージを OSS として公開しました。 GitHub: softjapan/php74-cve-patched softjapan/php74-cve-patched :::note alert このイメージは「応急処置」です。PHP 7.4 を安全なバージョンにするものではありません。 - 直るのは CVE-2026-109618 と CVE-2026-109619 の 2 件だけ です。7.4.33 より後に見つかったほかの問題は直っていません。 - ベース OS の Debian 11 (bullseye) は 2026-08 に LTS が終わっています。OpenSSL や Apache などの OS パッケージは今後更新されません。 - PHP プロジェクトや Docker 社の公式イメージではありません。 恒久的な対策は PHP 8.2 以降への移行 です。このイメージは、移行までの時間を稼ぐために使ってください。 ::: TL;DR - FROM php:7.4-apache + FROM ghcr.io/softjapan/php74-cve-patched:7.4-apache 1. FROM を 1 行差し替える(apache / fpm / cli、amd64 / arm64) 2. イメージを再ビルド・再デプロイし、PHP のワーカーをすべて再起動する 3. check-patched.sh で修正が入ったことを確認する 4. PHP 8.2 以降への移行計画を立てる(ここまでやって対応完了です) まず、自分の環境が脆弱か確認する 困ったことに、backport を当てても php -v は 7.4.33 のまま です。バージョン番号を見ても、対策済みかどうかは分かりません。 そこで、PHP のバイナリの中身を調べて判定するスクリプトを用意しました。 curl -fsSLO https://raw.githubusercontent.com/softjapan/php74-cve-patched/main/scripts/check-patched.sh sh check-patched.sh php:7.4-apache # イメージ sh check-patched.sh --container my-web-1 # 起動中のコンテナ sh check-patched.sh --local # このマシン(VM や物理サーバー) 公式の php:7.4-apache を調べた結果です。 Image: php:7.4-apache PHP version: 7.4.33 VULNERABLE /usr/lib/apache2/modules/libphp7.so VULNERABLE /usr/local/bin/php RESULT: VULNERABLE to CVE-2026-109618 / CVE-2026-109619 パッチを当てたイメージではこうなります。 Image: ghcr.io/softjapan/php74-cve-patched:7.4-apache PHP version: 7.4.33 patched /usr/lib/apache2/modules/libphp7.so patched /usr/local/bin/php RESULT: PATCHED (backport found in every PHP binary) - 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 以降は修正済みと判定します。それより古いバージョンは、backport で追加される関数 zend_new_array_singleton がバイナリにあるかどうかで判定します。 - CLI だけでなく、実際にリクエストを処理する libphp7.so(mod_php)や php-fpm も個別に調べます。CLI だけ直っていて Apache が古いまま、という状態も見つけられます。 - 終了コードは 0 が修正済み、1 が脆弱です。CI に組み込んで、脆弱なイメージをデプロイしないようにもできます。 :::note info この判定は簡易的なものです。ディストリビューションや LTS ベンダーが独自の方法で backport したパッケージは、「脆弱」と判定されることがあります。その場合はベンダーの情報を確認してください。 ::: 使い方 同じイメージを GHCR と Docker Hub の両方で公開しています。タグもダイジェストも同じです。 | 公式イメージ | GHCR | Docker Hub | |---|---|---| | php:7.4-apache | ghcr.io/softjapan/php74-cve-patched:7.4-apache | softjpn/php74-cve-patched:7.4-apache | | php:7.4-fpm | ghcr.io/softjapan/php74-cve-patched:7.4-fpm | softjpn/php74-cve-patched:7.4-fpm | | php:7.4-cli | ghcr.io/softjapan/php74-cve-patched:7.4-cli | softjpn/php74-cve-patched:7.4-cli | 公式イメージと同じ使い方ができることを重視しています。 - docker-php-ext-install / docker-php-ext-configure / pecl / php.ini-production がそのまま使えます - php -m の拡張モジュール一覧が公式イメージと同じであることを CI で確認しています - apt-get install も使えます(apt の参照先を archive.debian.org に変えてあります) Laravel 向けの例です。 FROM ghcr.io/softjapan/php74-cve-patched:7.4-apache RUN apt-get update && apt-get install -y --no-install-recommends \ libzip-dev libpng-dev libjpeg-dev libfreetype6-dev \ && rm -rf /var/lib/apt/lists/* \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j"$(nproc)" gd pdo_mysql zip bcmath opcache \ && a2enmod rewrite :::note alert イメージを差し替えただけでは終わりません。 実行中のコンテナやワーカーは古いバイナリのまま動いています。再ビルド・再デプロイして、PHP のワーカーをすべて再起動してください。最後に check-patched.sh --container <名前> で、動いているコンテナ が修正済みかを確認してください。 ::: 何を変えたのか 変更は最小限にしています。docker-library/php に残っている 最後の PHP 7.4 用 Dockerfile(commit 1361ba95) を元に、変えたのは次の 3 点だけです。 1. apt の参照先を archive.debian.org に変更: bullseye は通常のミラーから消えたため、apt-get update が 404 になります 2. PHP 7.4.33 のソースに backport を適用: patch -p1 --fuzz=0 で当てるので、少しでもずれていればビルドが失敗します 3. 修正が入ったことをビルド中に確認: php、php-fpm、libphp7.so のどれか 1 つでも修正が入っていなければ、ビルドを失敗させます 当てているパッチは、上流の php/php-src@712e60f と バイト単位で同一 です。CI が push のたびと毎週、次の点を確認しています。 - 同梱のパッチが上流の commit と同一であること - 上流の backport ブランチに新しい commit が入っていないこと(入っていれば CI が失敗して知らせます) 当初は社内で php:7.4-apache の上から ./configure をやり直す方法をとっていました。しかしこの方法には、configure のオプションが x86_64 向けに固定される、fpm / cli 版でオプションがずれる、といった問題がありました。公開版では公式の Dockerfile そのものを元にして、マルチアーキテクチャへの対応と公式との互換性を両立しています。 信頼して使うために セキュリティ目的のイメージを、知らない人が配っているものから取ってくるのは不安だと思います。そのため、検証できる材料をそろえました。 - イメージはリポジトリの GitHub Actions だけでビルドし、SBOM と provenance を付けています - cosign(keyless)で署名しています cosign verify ghcr.io/softjapan/php74-cve-patched:7.4-apache \ --certificate-identity-regexp '^https://github.com/softjapan/php74-cve-patched/' \ --certificate-oidc-issuer https://token.actions.githubusercontent.com - 本番環境ではダイジェスト(@sha256:...)で固定してください - このイメージを使わず、自分でビルドする手順 も公開しています。Docker を使わずソースからビルドしている環境向けに、patch -p1 で当てる手順も載せています イメージをすぐ差し替えられない場合の緩和策 advisory には、すぐに更新できない場合の緩和策も載っています。どれも攻撃の経路を一部ふさぐだけで、安全になるわけではない と明記されていますが、差し替えまでのつなぎや多層防御として使えます。 CVE-2026-109618(OOM による状態破損) - memory_limit=-1 を、アプリケーションが上書きできない方法(FPM プールや Apache の php_admin_value)で設定する。どこかの設定で有限の値に戻されていないかも確認する - その代わり、コンテナや cgroup のメモリ制限で、影響を受けたワーカーだけが止まるようにしておく - RLIMIT_AS / RLIMIT_DATA での代用はしない(脆弱な経路を逆に通る原因になる) - post_max_size を小さくする。アップロードがないなら 8M、あるなら 32M。upload_max_filesize は post_max_size より小さくする - Web サーバーやプロキシでも、リクエストサイズ、フィールド数、マルチパートの数、ヘッダー数などを制限する。Content-Length がないリクエストも対象に含める CVE-2026-109619(古いグローバル状態) - session.upload_progress.enabled=0 を設定し、ワーカーをすべて再起動する - php.ini、FPM プール、サーバー設定など、リクエストの解析前に効く場所で設定する。ini_set() や .user.ini では効果がない - 初期化前に警告を出すような、無効な設定や非推奨の設定をリクエストごとに適用しているなら取り除く(@ や display_errors で表示を隠しても意味はない) - 攻撃者が起こせる fatal error やタイムアウトを修正する このイメージには、上記の一部(session.upload_progress.enabled = 0 と、小さめの post_max_size / upload_max_filesize)をまとめた設定ファイルを同梱しています。デフォルトでは無効 です。PHP の挙動は公式イメージと変えていないので、使う場合は次の 1 行を追加してください。 RUN cp /usr/local/share/php74-cve-patched/zz-cve-2026-mitigations.ini "$PHP_INI_DIR/conf.d/" 応急処置のあとにやること 最後にもう一度書いておきます。このイメージは止血であって、治療ではありません。 - [ ] すべての PHP 7.4 環境を洗い出し、check-patched.sh で確認した - [ ] イメージを差し替え、再デプロイし、ワーカーを再起動した - [ ] 動いているコンテナ で check-patched.sh --container が PATCHED になった - [ ] 必要に応じて緩和策の設定も入れた - [ ] PHP 8.2 以降への移行計画と期限を決めた(8.2 も 2026-12-31 に EOL になるので、8.3 以降も検討する) - [ ] OS(Debian 11)も更新されないことを、関係者と共有した まとめ - CVE-2026-109618 / 109619 は、認証なしの RCE です。特に mod_php は最優先で対応してください - PHP 7.4 の公式 Docker イメージは今後も直りません。php:7.4-* を使っていれば脆弱なままです - php74-cve-patched は、FROM を 1 行変えるだけで公式の backport を取り込める 応急処置 です - 恒久的な対策は PHP 8.2 以降への移行です PHP 8.0 / 8.1 版(こちらも公式の backport があります)や Alpine 版も検討しています。必要な方は Issue で教えてください。この記事が役に立ったら、Qiita の LGTM や GitHub の ⭐ をもらえるとうれしいです。同じように困っている人に見つけてもらいやすくなります。 softjapan/php74-cve-patched 参考 - PHP: News Archive 2026(2026-10-21 Security advisory) - GHSA-w8hw-w9fx-j79w(CVE-2026-109618) - GHSA-6wmf-4rv5-p3rp(CVE-2026-109619) - php-src: PHP-7.4-CVE-2026-109618-109619 ブランチ

  2. DEV · · @softjapan

    Stopgap fix: patch CVE-2026-109618 / 109619 (PHP RCE) while still on PHP 7.4 On 2026-10-21 the PHP project disclosed two unauthenticated remote code execution vulnerabilities (php.net announcement): - CVE-2026-109618 (GHSA-w8hw-w9fx-j79w): out-of-memory handling can interrupt PHP while internal request data is only partly initialized, and request cleanup may then treat that invalid data as valid. - CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp): internal state owned by a request can survive after its memory is freed, and a later request on the same worker may use it. Every PHP installation that serves web requests is affected: PHP-FPM, Apache mod_php, php-cgi and others. The advisory rates the risk highest for mod_php, where an unauthenticated request can trigger the attack before any application code runs. Fixed releases exist only for PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12. PHP 7.4 is end of life, but because the bugs are so severe, the PHP security team published minimal source backports for 7.4, 8.0 and 8.1. The official Docker images php:7.4-* will not be rebuilt. If your Dockerfile says FROM php:7.4-apache, you stay vulnerable unless you act. So I rebuilt those images with the backport applied and published them as open source: 👉 **softjapan/php74-cve-patched** > ⚠️ This is a stopgap, not a fix for PHP 7.4. > > - Only CVE-2026-109618 and CVE-2026-109619 are fixed. Other issues found after 7.4.33 are not. > - The base OS, Debian 11 (bullseye), reached end of LTS in 2026-08. OS packages such as OpenSSL and Apache receive no more updates. > - These are not official images from the PHP project or Docker. > > The real fix is upgrading to PHP 8.2 or newer. Use these images to buy time for that upgrade. TL;DR - FROM php:7.4-apache + FROM ghcr.io/softjapan/php74-cve-patched:7.4-apache 1. Change one FROM line (apache / fpm / cli, amd64 / arm64). 2. Rebuild, redeploy and restart every PHP worker. 3. Confirm the fix with check-patched.sh. 4. Plan your upgrade to PHP 8.2+. You are done only after this step. Step 1: check whether you are vulnerable The catch: after the backport, php -v still prints 7.4.33. The version number cannot tell you whether you are protected. This script looks inside the PHP binaries instead: curl -fsSLO https://raw.githubusercontent.com/softjapan/php74-cve-patched/main/scripts/check-patched.sh sh check-patched.sh php:7.4-apache # an image sh check-patched.sh --container my-web-1 # a running container sh check-patched.sh --local # this machine (VM / bare metal) The official image: Image: php:7.4-apache PHP version: 7.4.33 VULNERABLE /usr/lib/apache2/modules/libphp7.so VULNERABLE /usr/local/bin/php RESULT: VULNERABLE to CVE-2026-109618 / CVE-2026-109619 The patched image: Image: ghcr.io/softjapan/php74-cve-patched:7.4-apache PHP version: 7.4.33 patched /usr/lib/apache2/modules/libphp7.so patched /usr/local/bin/php RESULT: PATCHED (backport found in every PHP binary) - PHP 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 and newer count as fixed. Older versions are checked for zend_new_array_singleton, a function the backport adds. - It checks each SAPI binary separately: the CLI, plus libphp7.so (mod_php) and php-fpm, which are what actually serve your requests. That catches a patched CLI next to an unpatched Apache module. - Exit code 0 means patched and 1 means vulnerable, so you can block vulnerable images in CI. The check is a heuristic. A backport from a distribution or LTS vendor written a different way may show as vulnerable. In that case, check with your vendor. Step 2: switch images The same images, with the same tags and digests, are on two registries: | Official image | GHCR | Docker Hub | |---|---|---| | php:7.4-apache | ghcr.io/softjapan/php74-cve-patched:7.4-apache | softjpn/php74-cve-patched:7.4-apache | | php:7.4-fpm | ghcr.io/softjapan/php74-cve-patched:7.4-fpm | softjpn/php74-cve-patched:7.4-fpm | | php:7.4-cli | ghcr.io/softjapan/php74-cve-patched:7.4-cli | softjpn/php74-cve-patched:7.4-cli | They work exactly like the official images: - docker-php-ext-install, docker-php-ext-configure, pecl and php.ini-production all work as before. - CI checks that php -m lists the same extensions as the official image. - apt-get install works, because apt now points at archive.debian.org. Example for Laravel: FROM ghcr.io/softjapan/php74-cve-patched:7.4-apache RUN apt-get update && apt-get install -y --no-install-recommends \ libzip-dev libpng-dev libjpeg-dev libfreetype6-dev \ && rm -rf /var/lib/apt/lists/* \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j"$(nproc)" gd pdo_mysql zip bcmath opcache \ && a2enmod rewrite > Changing the image is not enough on its own. Containers and workers that are already running keep the old binaries. Rebuild, redeploy and restart every PHP worker, then run check-patched.sh --container <name> against the running container. What exactly changed Very little. The images start from the last PHP 7.4 Dockerfiles in docker-library/php (commit 1361ba95) and change three things: 1. apt uses archive.debian.org. Bullseye has left the regular mirrors, so apt-get update there returns 404. 2. The backport is applied to the PHP 7.4.33 source with patch -p1 --fuzz=0. If it does not apply cleanly, the build fails. 3. The build checks the result. If php, php-fpm or libphp7.so is missing the fix, the build fails. The patch is byte-identical to the upstream commit php/php-src@712e60f. On every push and every week, CI checks two things: - The vendored patch still matches the upstream commit. - The upstream backport branch has no new commits. If it does, CI fails so a new patch can be shipped. My first internal version re-ran ./configure on top of php:7.4-apache. That approach hard-coded x86_64 options and let the fpm and cli builds drift from each other. Starting from the official Dockerfiles keeps the images compatible with the official ones and makes multi-arch builds straightforward. Trust, but verify You probably should not pull a security image from a stranger on faith, so everything here can be checked: - Images are built only by GitHub Actions in the repository, with SBOM and provenance attestations. - Images are signed with cosign (keyless): cosign verify ghcr.io/softjapan/php74-cve-patched:7.4-apache \ --certificate-identity-regexp '^https://github.com/softjapan/php74-cve-patched/' \ --certificate-oidc-issuer https://token.actions.githubusercontent.com - Pin a digest (@sha256:...) in production. - Or skip these images and build them yourself. The guide also covers applying the patch with patch -p1 if you build PHP from source without Docker. Mitigations if you cannot switch right away The advisory also lists mitigations. It is clear that they only block some attack paths and do not make an installation safe, but they are useful as a bridge until you switch, and as defense in depth afterwards. CVE-2026-109618 (OOM corruption) - Set memory_limit=-1 in a way applications cannot override, such as php_admin_value in the FPM pool or Apache config. Check that no other setting brings back a finite limit. - Use a container or cgroup memory limit instead, ideally one that kills only the affected worker. - Do not use RLIMIT_AS or RLIMIT_DATA as a substitute. They can cause the very allocation failure you are trying to avoid. - Lower post_max_size: 8M if you have no file uploads, 32M if you do. Keep upload_max_filesize below post_max_size. - Also limit request size, field count, multipart part count, header count and nesting depth at the web server or proxy, including for requests without a usable Content-Length. CVE-2026-109619 (stale global state) - Set session.upload_progress.enabled=0 and restart every worker. - Set it in php.ini, the FPM pool or the server config, which apply before request parsing. ini_set() and .user.ini do not help. - Remove invalid or deprecated settings applied per request that emit diagnostics before initialization. Hiding the diagnostics with @ or display_errors does not help. - Fix fatal errors and timeouts that an attacker can trigger. The images ship an optional file with some of these settings (session.upload_progress.enabled = 0 and lower post_max_size / upload_max_filesize). It is disabled by default, so PHP behaves exactly like the official image. To enable it: RUN cp /usr/local/share/php74-cve-patched/zz-cve-2026-mitigations.ini "$PHP_INI_DIR/conf.d/" After the stopgap One more time: this stops the bleeding. It does not cure the patient. - [ ] Find every PHP 7.4 environment and run check-patched.sh on it. - [ ] Switch images, redeploy and restart the workers. - [ ] Confirm check-patched.sh --container reports PATCHED on the running containers. - [ ] Add the mitigation settings where they make sense. - [ ] Set a plan and a deadline for moving to PHP 8.2+. PHP 8.2 itself reaches end of life on 2026-12-31, so consider 8.3 or newer. - [ ] Tell your team that the OS (Debian 11) is not getting updates either. Summary - CVE-2026-109618 and CVE-2026-109619 are unauthenticated RCEs. Treat mod_php as top priority. - The official PHP 7.4 Docker images will not be fixed. If you use php:7.4-*, you stay vulnerable. - php74-cve-patched is a stopgap that brings in the official backport with a one-line FROM change. - The real fix is upgrading to PHP 8.2 or newer. PHP 8.0 / 8.1 images (official backports exist for those too) and Alpine variants are on the roadmap. Open an issue if you need one. And if this saved you an emergency upgrade, a ⭐ on GitHub helps other people stuck on PHP 7.4 find it. 👉 **softjapan/php74-cve-patched** References - PHP: News Archive 2026 (2026-10-21 security advisory) - GHSA-w8hw-w9fx-j79w (CVE-2026-109618) - GHSA-6wmf-4rv5-p3rp (CVE-2026-109619) - php-src branch PHP-7.4-CVE-2026-109618-109619

  3. Zenn · · @japan

    【応急処置】PHP 7.4 のまま CVE-2026-109618 / 109619(RCE)を塞ぐ Docker イメージを公開しました はじめに 2026-10-21、PHP プロジェクトが 認証なしでリモートコード実行(RCE)が可能な脆弱性を 2 件 公表しました(php.net のアナウンス)。 CVE-2026-109618(GHSA-w8hw-w9fx-j79w): メモリ不足(OOM)の処理が、内部のリクエストデータの初期化途中で PHP を中断させ、壊れたデータがクリーンアップ時に正しいデータとして扱われる CVE-2026-109619(GHSA-6wmf-4rv5-p3rp): 解放済みのメモリを指すリクエスト用の内部状態が残り、同じワーカーが処理する次のリクエストでそれが使われる 影響を受けるのは、Web リクエストを処理するすべての PHP(PHP-FPM、Apache mod_php、php-cgi など)です。advisory は mod_php のリスクが最も高い としており、アプリケーションのコードが動く前に攻撃が成立する実証コードもあるとしています。 修正版が出たのは PHP 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 だけです。PHP 7.4 は EOL なので修正版は出ません。ただ、深刻度を考慮して、PHP セキュリティチームが 7.4 / 8.0 / 8.1 向けに 最小限のソース backport を公開しています。 一方で、Docker の公式イメージ php:7.4-* が再ビルドされることはありません。FROM php:7.4-apache のまま運用しているシステムは、何もしなければ脆弱なまま です。 そこで、この backport を当てて再ビルドした php:7.4-* 互換のイメージを OSS として公開しました。 softjapan/php74-cve-patched ! このイメージは「応急処置」です。PHP 7.4 を安全なバージョンにするものではありません。 直るのは CVE-2026-109618 と CVE-2026-109619 の 2 件だけ です。7.4.33 より後に見つかったほかの問題は直っていません。 ベース OS の Debian 11 (bullseye) は 2026-08 に LTS が終わっています。OpenSSL や Apache などの OS パッケージは今後更新されません。 PHP プロジェクトや Docker 社の公式イメージではありません。 恒久的な対策は PHP 8.2 以降への移行 です。このイメージは、移行までの時間を稼ぐために使ってください。 TL;DR - FROM php:7.4-apache - FROM ghcr.io/softjapan/php74-cve-patched:7.4-apache FROM を 1 行差し替える(apache / fpm / cli、amd64 / arm64) イメージを再ビルド・再デプロイし、PHP のワーカーをすべて再起動する check-patched.sh で修正が入ったことを確認する PHP 8.2 以降への移行計画を立てる(ここまでやって対応完了です) まず、自分の環境が脆弱か確認する 困ったことに、backport を当てても php -v は 7.4.33 のまま です。バージョン番号を見ても、対策済みかどうかは分かりません。 そこで、PHP のバイナリの中身を調べて判定するスクリプトを用意しました。 curl -fsSLO raw.githubusercontent.com sh check-patched.sh php:7.4-apache # イメージ sh check-patched.sh --container my-web-1 # 起動中のコンテナ sh check-patched.sh --local # このマシン(VM や物理サーバー) 公式の php:7.4-apache を調べた結果です。 Image: php:7.4-apache PHP version: 7.4.33 VULNERABLE /usr/lib/apache2/modules/libphp7.so VULNERABLE /usr/local/bin/php RESULT: VULNERABLE to CVE-2026-109618 / CVE-2026-109619 パッチを当てたイメージではこうなります。 Image: ghcr.io/softjapan/php74-cve-patched:7.4-apache PHP version: 7.4.33 patched /usr/lib/apache2/modules/libphp7.so patched /usr/local/bin/php RESULT: PATCHED (backport found in every PHP binary) 8.2.35 / 8.3.36 / 8.4.27 / 8.5.12 以降は修正済みと判定します。それより古いバージョンは、backport で追加される関数 zend_new_array_singleton がバイナリにあるかどうかで判定します。 CLI だけでなく、実際にリクエストを処理する libphp7.so(mod_php)や php-fpm も個別に調べます。CLI だけ直っていて Apache が古いまま、という状態も見つけられます。 終了コードは 0 が修正済み、1 が脆弱です。CI に組み込んで、脆弱なイメージをデプロイしないようにもできます。 ! この判定は簡易的なものです。ディストリビューションや LTS ベンダーが独自の方法で backport したパッケージは、「脆弱」と判定されることがあります。その場合はベンダーの情報を確認してください。 使い方 同じイメージを GHCR と Docker Hub の両方で公開しています。タグもダイジェストも同じです。 公式イメージ GHCR Docker Hub php:7.4-apache ghcr.io/softjapan/php74-cve-patched:7.4-apache softjpn/php74-cve-patched:7.4-apache php:7.4-fpm ghcr.io/softjapan/php74-cve-patched:7.4-fpm softjpn/php74-cve-patched:7.4-fpm php:7.4-cli ghcr.io/softjapan/php74-cve-patched:7.4-cli softjpn/php74-cve-patched:7.4-cli 公式イメージと同じ使い方ができることを重視しています。 docker-php-ext-install / docker-php-ext-configure / pecl / php.ini-production がそのまま使えます php -m の拡張モジュール一覧が公式イメージと同じであることを CI で確認しています apt-get install も使えます(apt の参照先を archive.debian.org に変えてあります) Laravel 向けの例です。 FROM ghcr.io/softjapan/php74-cve-patched:7.4-apache RUN apt-get update && apt-get install -y --no-install-recommends \ libzip-dev libpng-dev libjpeg-dev libfreetype6-dev \ && rm -rf /var/lib/apt/lists/* \ && docker-php-ext-configure gd --with-freetype --with-jpeg \ && docker-php-ext-install -j"$(nproc)" gd pdo_mysql zip bcmath opcache \ && a2enmod rewrite ! イメージを差し替えただけでは終わりません。 実行中のコンテナやワーカーは古いバイナリのまま動いています。再ビルド・再デプロイして、PHP のワーカーをすべて再起動してください。最後に check-patched.sh --container <名前> で、動いているコンテナ が修正済みかを確認してください。 何を変えたのか 変更は最小限にしています。docker-library/php に残っている 最後の PHP 7.4 用 Dockerfile(commit 1361ba95) を元に、変えたのは次の 3 点だけです。 apt の参照先を archive.debian.org に変更: bullseye は通常のミラーから消えたため、apt-get update が 404 になります PHP 7.4.33 のソースに backport を適用: patch -p1 --fuzz=0 で当てるので、少しでもずれていればビルドが失敗します 修正が入ったことをビルド中に確認: php、php-fpm、libphp7.so のどれか 1 つでも修正が入っていなければ、ビルドを失敗させます 当てているパッチは、上流の php/php-src@712e60f と バイト単位で同一 です。CI が push のたびと毎週、次の点を確認しています。 同梱のパッチが上流の commit と同一であること 上流の backport ブランチに新しい commit が入っていないこと(入っていれば CI が失敗して知らせます) 当初は社内で php:7.4-apache の上から ./configure をやり直す方法をとっていました。しかしこの方法には、configure のオプションが x86_64 向けに固定される、fpm / cli 版でオプションがずれる、といった問題がありました。公開版では公式の Dockerfile そのものを元にして、マルチアーキテクチャへの対応と公式との互換性を両立しています。 信頼して使うために セキュリティ目的のイメージを、知らない人が配っているものから取ってくるのは不安だと思います。そのため、検証できる材料をそろえました。 イメージはリポジトリの GitHub Actions だけでビルドし、SBOM と provenance を付けています cosign(keyless)で署名しています cosign verify ghcr.io/softjapan/php74-cve-patched:7.4-apache \ --certificate-identity-regexp '^softjapan/php74-cve-patched' \ --certificate-oidc-issuer token.actions.githubusercontent.com 本番環境ではダイジェスト(@sha256:...)で固定してください このイメージを使わず、自分でビルドする手順 も公開しています。Docker を使わずソースからビルドしている環境向けに、patch -p1 で当てる手順も載せています イメージをすぐ差し替えられない場合の緩和策 advisory には、すぐに更新できない場合の緩和策も載っています。どれも攻撃の経路を一部ふさぐだけで、安全になるわけではない と明記されていますが、差し替えまでのつなぎや多層防御として使えます。 CVE-2026-109618(OOM による状態破損) memory_limit=-1 を、アプリケーションが上書きできない方法(FPM プールや Apache の php_admin_value)で設定する。どこかの設定で有限の値に戻されていないかも確認する その代わり、コンテナや cgroup のメモリ制限で、影響を受けたワーカーだけが止まるようにしておく RLIMIT_AS / RLIMIT_DATA での代用はしない(脆弱な経路を逆に通る原因になる) post_max_size を小さくする。アップロードがないなら 8M、あるなら 32M。upload_max_filesize は post_max_size より小さくする Web サーバーやプロキシでも、リクエストサイズ、フィールド数、マルチパートの数、ヘッダー数などを制限する。Content-Length がないリクエストも対象に含める CVE-2026-109619(古いグローバル状態) session.upload_progress.enabled=0 を設定し、ワーカーをすべて再起動する php.ini、FPM プール、サーバー設定など、リクエストの解析前に効く場所で設定する。ini_set() や .user.ini では効果がない 初期化前に警告を出すような、無効な設定や非推奨の設定をリクエストごとに適用しているなら取り除く(@ や display_errors で表示を隠しても意味はない) 攻撃者が起こせる fatal error やタイムアウトを修正する このイメージには、上記の一部(session.upload_progress.enabled = 0 と、小さめの post_max_size / upload_max_filesize)をまとめた設定ファイルを同梱しています。デフォルトでは無効 です。PHP の挙動は公式イメージと変えていないので、使う場合は次の 1 行を追加してください。 RUN cp /usr/local/share/php74-cve-patched/zz-cve-2026-mitigations.ini "$PHP_INI_DIR/conf.d/" 応急処置のあとにやること 最後にもう一度書いておきます。このイメージは止血であって、治療ではありません。 すべての PHP 7.4 環境を洗い出し、check-patched.sh で確認した イメージを差し替え、再デプロイし、ワーカーを再起動した 動いているコンテナ で check-patched.sh --container が PATCHED になった 必要に応じて緩和策の設定も入れた PHP 8.2 以降への移行計画と期限を決めた(8.2 も 2026-12-31 に EOL になるので、8.3 以降も検討する) OS(Debian 11)も更新されないことを、関係者と共有した まとめ CVE-2026-109618 / 109619 は、認証なしの RCE です。特に mod_php は最優先で対応してください PHP 7.4 の公式 Docker イメージは今後も直りません。php:7.4-* を使っていれば脆弱なままです php74-cve-patched は、FROM を 1 行変えるだけで公式の backport を取り込める 応急処置 です 恒久的な対策は PHP 8.2 以降への移行です PHP 8.0 / 8.1 版(こちらも公式の backport があります)や Alpine 版も検討しています。必要な方は Issue で教えてください。役に立ったら GitHub で ⭐ をもらえるとうれしいです。同じように困っている人に見つけてもらいやすくなります。 softjapan/php74-cve-patched 参考 PHP: News Archive 2026(2026-10-21 Security advisory) GHSA-w8hw-w9fx-j79w(CVE-2026-109618) GHSA-6wmf-4rv5-p3rp(CVE-2026-109619) php-src: PHP-7.4-CVE-2026-109618-109619 ブランチ

  4. DEV · · @sarantoon

    PHP หลังแพตช์ 10 ชั่วโมง: รุ่นไหนโดนอะไร และแต่ละรุ่นต้องทำอย่างไร? PHP หลังแพตช์ 10 ชั่วโมง: รุ่นไหนโดนอะไร และแต่ละรุ่นต้องทำอย่างไร? โดย Nokka (นก-กา) | นักเขียนอิสระสาย AI และระบบเปิด | ตรวจสอบข้อมูล ณ 22 ต.ค. 2026 เวลา 07:40 น. บทความนี้เขียนโดย AI (deepseek-v4.1-flash · ผู้ให้บริการโมเดล: ollama-cloud) ผ่าน Hermes Agent ภายใต้การควบคุมและตรวจสอบคุณภาพโดยมนุษย์ - Nokka (นก-กา) เมื่อคืนแพตช์ออกแล้ว และเมื่อเช้าก็มีคนยิงเข้ามา เมื่อวานเวลา 21:00 ตามเวลาไทย PHP ปล่อยแพตช์ชุดเดียวที่ครอบสองช่องโหว่ในสี่รุ่น คือ 8.5.12, 8.4.27, 8.3.36 และ 8.2.35 [1] ผ่านมาไม่ถึงวัน สถานการณ์เปลี่ยนจาก "เตรียมตัว" เป็น "มีคนเริ่มยิงแล้ว" ถ้าจะอ่านข่าวช่วงนี้ให้ถูก ต้องแยกสามชั้นนี้ให้ออก เพราะข่าวแต่ละสำนักพูดคนละชั้น ชั้นที่หนึ่ง การสาธิตของนักวิจัย Sansec รายงานว่าทีมวิจัยยืนยันการโจมตีแบบไม่ต้องยืนยันตัวตนได้จริงบน Magento 2.4.9 และแอป PHP อีกสิบตัว และระบุว่าค่าตั้งเริ่มต้นของ PHP ก็อยู่ในข่ายที่โดน [11] ประกาศของทีม PHP เองก็ระบุว่า เส้นทาง RCE ที่เกี่ยวกับวงจร session ถูกตรวจสอบยืนยันแล้วทั้งบน mod_php และ FPM [12] ชั้นที่สอง ความพยายามโจมตีจริง watchTowr บอกกับ SecurityWeek ว่าเริ่มมีทราฟฟีโจมตีเข้ามาชนเซนเซอร์ของบริษัทราวเวลาเดียวกับที่แพตช์ออก แต่ยังไม่มีรายใดสำเร็จ [3] บริษัท Hadrian ใช้ถ้อยแรงกว่านั้น คือบอกว่าเห็น php2shell ถูกใช้โจมตีในสนามเป็นวงกว้างแล้ว และเส้นทางที่เจอบ่อยที่สุดคือช่อง session upload progress [3] ส่วน Patchstack, Cloudflare และ Vega ก็รายงานว่าเจอของแบบเดียวกันเข้ามาที่ระบบเฝ้าดูของแต่ละเจ้า [3] ชั้นที่สาม การยึดเครื่องสำเร็จที่ยืนยันได้ ชั้นนี้ยังว่างอยู่ เจค นอตต์ หัวหน้าฝ่ายข่าวกรองภัยคุกคามของ watchTowr พูดไว้ตรง ๆ ว่า ถึงตอนนี้ยังไม่มีใครทำสำเร็จ แต่เขาไม่คิดว่าจะอยู่อย่างนี้ได้นาน [3] และ CISA ออกประกาศเตือนเมื่อวานโดยระบุว่า ณ เวลาที่เผยแพร่ ยังไม่พบการโจมตี [2] สามชั้นนี้ไม่ขัดกัน การสาธิตในแล็บไม่ใช่การยึดเครื่องจริง และถ้อยที่ว่า php2shell ถูกใช้โจมตีในสนาม กับการยืนยันว่ายึดเครื่องได้สำเร็จ ก็ยังต่างกันอยู่ สรุปสั้นสำหรับคนที่ไม่มีเวลาอ่าน ถ้าคุณจำได้แค่บรรทัดเดียว ให้จำบรรทัดนี้ PHP 8.2 ถึง 8.5 อัปเดตได้ทันทีเป็น 8.2.35, 8.3.36, 8.4.27 หรือ 8.5.12 ส่วน 8.1, 8.0 และ 7.4 ต้องใช้ source backport หรือแพ็กเกจจากผู้จำหน่าย และ 7.3 ลงไปจนถึง 5.x ทีม PHP ไม่มีแพตช์ให้ และไม่มี source backport ทางการ ผู้จำหน่ายบางรายอาจมี ต้องถามก่อน รุ่นไหนบ้างที่ถือว่ามีปัญหา คำถามนี้มีสามคำตอบที่ต่างกัน ขึ้นกับว่าถามใคร และผมคิดว่านี่คือจุดที่คนสับสนมากที่สุด คำตอบที่ 1 ของผู้ดูแล PHP ประกาศอย่างเป็นทางการระบุขอบเขตว่า PHP 8.2 ก่อน 8.2.35, PHP 8.3 ก่อน 8.3.36, PHP 8.4 ก่อน 8.4.27 และ PHP 8.5 ก่อน 8.5.12 [4] ผมอ่านว่านี่คือขอบเขตที่เขาแก้และรับรอง ไม่ใช่ขอบเขตทั้งหมดที่โดน อีกชั้นที่ประกาศระบุแยกไว้ คือความเสี่ยงไม่ได้เท่ากันทุก SAPI ประกาศเขียนว่า mod_php เสี่ยงสูงสุด เพราะ Apache เรียก shutdown โดยไม่มีเงื่อนไขเมื่อเกิดปัญหา ส่วน FPM มีเงื่อนไขมากกว่า คือต้องมีตัวกระตุ้นจากแอปที่ทำงานอยู่จริงและต้องเกิด fatal error ในจังหวะที่เหมาะ [1] [12] คำตอบที่ 2 ของฐานข้อมูลกลาง NVD ขึ้นทะเบียนทั้งสองรหัสเมื่อวันที่ 21 ตุลาคม เวลา 14:17 UTC และระบุช่วงที่กระทบว่าคือทุกเวอร์ชันก่อน 8.2.35, 8.3.0 ถึงก่อน 8.3.36, 8.4.0 ถึงก่อน 8.4.27 และ 8.5.0 ถึงก่อน 8.5.12 [5] การเขียนว่า "ก่อน 8.2.35" แบบไม่มีจุดเริ่มต้น แปลว่าทุกอย่างที่ต่ำกว่านั้นถูกนับรวมไปด้วย คำตอบที่ 3 ของทีมที่ค้นพบ Wiz Research หนึ่งในสามทีมที่พบช่องโหว่ชุดนี้ ร่วมกับ Calif ของ Ryan Austin และ OpenAI เขียนว่า PHP เกือบทุกรุ่นที่ออกในทศวรรษที่ผ่านมามีปัญหาอย่างน้อยหนึ่งตัว ย้อนไปถึงรุ่น 5.4 [6] และเขาระบุด้วยว่าช่องโหว่ชุดนี้ไม่ได้ให้แค่การรันโค้ด แต่ยังอ่านหน่วยความจำของโปรเซสได้ด้วย ซึ่งอาจมีรหัสผ่าน โทเคน API หรือใบรับรองของคำขออื่นหลุดออกไป [6] แนวทางแยกตามรุ่น นี่คือส่วนที่ผมอยากให้อ่านช้า ๆ เพราะสิ่งที่ต้องทำต่างกันจริงในแต่ละรุ่น ถ้าคุณอยู่บน PHP 8.5 อัปเดตเป็น 8.5.12 [1] นี่คือรุ่นที่ได้รับการสนับสนุนเต็มรูปแบบ และเป็นรุ่นที่แพตช์ออกพร้อมกับรุ่นอื่นในคืนเดียวกัน ถ้าคุณใช้ PHP 8.5 อยู่ ยังมีมาตรการเสริมเฉพาะรุ่นนี้คือตั้ง fatal_error_backtraces=0 แล้วรีสตาร์ต worker ทุกตัว ซึ่ง PHP ระบุว่าช่วยปิดเส้นทางที่ยืนยันแล้วทางหนึ่ง แต่ไม่ใช่ทั้งหมด [1] ถ้าคุณอยู่บน PHP 8.4 อัปเดตเป็น 8.4.27 [1] สถานะของ 8.4 คือสนับสนุนเต็มถึงสิ้นปี 2026 แล้วต่อด้วยช่วงรับเฉพาะแพตช์ความปลอดภัยไปจนถึงสิ้นปี 2028 [7] แปลว่าอัปเดตตอนนี้แล้วยังได้ใช้งานอีกกว่าสองปี ถ้าคุณอยู่บน PHP 8.3 อัปเดตเป็น 8.3.36 [1] รุ่น 8.3 เข้าสู่ช่วงรับเฉพาะแพตช์ความปลอดภัยแล้ว แต่ยังได้แพตช์ตัวนี้ครบ ถ้าคุณอยู่บน PHP 8.2 อัปเดตเป็น 8.2.35 [1] มีกำหนดที่ควรจดไว้คือ 8.2 จะสิ้นสุดช่วงรับแพตช์ความปลอดภัยในอีกสองเดือนข้างหน้า คือ 31 ธันวาคม 2026 [7] ถ้าคุณยังอยู่บน 8.2 ควรวางแผนขึ้น 8.4 ไว้ในไตรมาสนี้ เพราะ 8.4 ได้รับการสนับสนุนไปถึงสิ้นปี 2028 ส่วน 8.3 รับเฉพาะแพตช์ความปลอดภัยถึงสิ้นปี 2027 [7] ถ้าต้องเลือกรุ่นปลายทางเดียว ผมเลือก 8.4 ถ้าคุณอยู่บน PHP 8.1 PHP ไม่ปล่อยรุ่นใหม่ให้ 8.1 แล้ว แต่ทีมความปลอดภัยทำ source backport ให้ คือแบรนช์ PHP-8.1-CVE-2026-109618-109619 บน GitHub [1] [8] คำว่า source backport หมายความว่าคุณต้องดึงโค้ดไปคอมไพล์เอง ไม่มีไฟล์ไบนารีสำเร็จรูปจากทีม PHP ให้โหลด ถ้าคุณใช้ดิสทริบิวชันที่มีสัญญาณสนับสนุนระยะยาว ให้เช็กแพ็กเกจจากผู้จำหน่ายก่อน เพราะ PHP ระบุว่าผู้จำหน่ายลินุกซ์และผู้ให้บริการ LTS ได้รับแพตช์ล่วงหน้าแล้ว [1] ถ้าทำทั้งสองทางไม่ได้จริง ๆ CISA แนะนำให้เอาระบบออกจากอินเทอร์เน็ตจนกว่าจะแพตช์หรืออัปเกรดได้ [2] ถ้าคุณอยู่บน PHP 8.0 หรือ 7.4 สถานะเหมือน 8.1 คือมี source backport ให้ แต่ไม่มีรุ่นใหม่ให้ติดตั้ง โดยแบรนช์คือ PHP-8.0-CVE-2026-109618-109619 และ PHP-7.4-CVE-2026-109618-109619 [1] [8] ผมอ่านประกาศแล้วเห็นว่าการที่ PHP ยอมทำ backport ให้สองรุ่นที่หมดอายุไปนานแล้ว เป็นสัญญาณว่าทีมตระหนักดีว่าคนจำนวนมากยังค้างอยู่บนรุ่นเหล่านี้ แต่การคอมไพล์เองไม่ใช่ทางเลือกของทุกคน โดยเฉพาะคนที่ใช้โฮสติ้ง ถ้าคุณอยู่บน PHP 7.3 หรือต่ำกว่า รวมถึง 5.x ตรงนี้คือจุดที่ผมอยากพูดตรง ๆ ว่า ทีม PHP ไม่มีแพตช์ให้ และไม่มี source backport ทางการให้ การทำ backport ของ PHP หยุดที่ 7.4 ไม่ได้ไล่ลงไปถึง 7.3 หรือ 5.x [1] และหน้า EOL ของ php.net ก็ระบุรุ่นเก่าเหล่านี้หมด support ไปนานแล้ว [9] แต่ประโยคนี้ไม่ได้แปลว่าไม่มีใครแพตช์ให้เลย เพราะประกาศของ PHP เองบอกว่าผู้จำหน่ายดิสทริบิวชันและผู้ให้บริการ LTS บางรายออกแพตช์ย้อนหลังเองได้ [1] ถ้าคุณอยู่ในดิสทริบิวชันแบบนั้น ให้ถามผู้จำหน่ายก่อนตัดสินใจ Wiz ระบุว่าช่องโหว่ย้อนไปถึง 5.4 [6] และ Sansec เขียนว่าช่องโหว่นี้กระทบเว็บเซิร์ฟเวอร์ที่รัน PHP 5.4 ขึ้นไป โดยโค้ดที่เปราะบางมีมาตั้งแต่ 5.4.0 ที่ออกในปี 2012 [11] ทางเลือกที่มีคือย้ายขึ้นรุ่นที่ยังได้รับการสนับสนุน หรือเอาออกจากอินเทอร์เน็ต หรือวางไว้หลัง WAF ที่ CISA บอกว่าช่วยได้บางส่วน [2] ส่วนการวางไว้หลัง VPN เป็นข้อเสนอของผมเอง ไม่ใช่ถ้อยของ CISA ผมคิดว่านี่คือกลุ่มที่ต้องตัดสินใจเชิงธุรกิจ ไม่ใช่เชิงเทคนิค เพราะการย้ายเว็บที่รันบน PHP 5 ขึ้นมา 8.x อาจต้องแก้โค้ดจำนวนมาก ถ้าคุณใช้คอนเทนเนอร์ อิมเมจ php อย่างเป็นทางการบน Docker ถูกอัปเดตแล้ว โดย pull request ในคลัง docker-library/php ถูกรวมเมื่อวันที่ 21 ตุลาคม เวลา 14:19 UTC หรือ 19 นาทีหลังแพตช์ออก [10] ถ้าคุณล็อกแท็กเป็นรุ่นเจาะจง เช่น php:8.2-fpm ให้ดึงอิมเมจใหม่และตรวจว่าข้างในเป็น 8.2.35 จริง ไม่ใช่แค่เชื่อแท็ก ถ้าคุณใช้โฮสติ้งแชร์หรือแผงควบคุม คุณไม่ได้เป็นคนแพตช์เอง คำถามที่ต้องส่งไปหาผู้ให้บริการมีสามข้อ - เว็บของฉันรัน PHP รุ่นอะไร - มีแผนติดตั้ง 8.2.35, 8.3.36, 8.4.27 หรือ 8.5.12 เมื่อไหร่ - ถ้ารุ่นที่ใช้อยู่ไม่มีแพตช์ จะย้ายขึ้นรุ่นที่ได้รับการสนับสนุนให้เมื่อไหร่ ผมไม่มีข้อมูลว่าผู้ให้บริการรายใดในไทยอัปเดตแล้วหรือยัง จึงไม่สามารถบอกได้ว่าคุณปลอดภัยหรือไม่ ต้องถามตรง ๆ เท่านั้น ถ้ายังแพตช์ไม่ได้ ระหว่างนี้ทำอะไรได้ PHP ระบุชัดว่าไม่มีมาตรการตั้งค่าที่ทำให้ปลอดภัยได้ทั้งหมด และการอัปเดตคือทางเดียวที่สมบูรณ์ [1] แต่มีมาตรการที่ลดความเสี่ยงเฉพาะเส้นทางได้ สองชุดนี้แยกตามรหัสช่องโหว่ สำหรับ CVE-2026-109618 (ช่อง OOM) ตั้ง memory_limit=-1 ผ่าน php_admin_value ใน FPM pool หรือในคอนฟิก Apache เพื่อไม่ให้แอปเขียนทับได้ แล้วตรวจว่าไม่มี pool หรือไดเรกทอรีใดตั้งค่ากลับเป็นค่าจำกัด [1] ตั้ง post_max_size ให้ต่ำ ถ้าไม่มีการอัปโหลดไฟล์ให้ใช้ 8M ถ้ามีให้ใช้ 32M และให้ upload_max_filesize ต่ำกว่า post_max_size [1] พิจารณาตั้งขีดจำกัดที่เว็บเซิร์ฟเวอร์หรือพร็อกซีด้วย ทั้งขนาดคำขอที่นับหลังถอดรหัส จำนวนฟิลด์ จำนวน part ใน multipart จำนวน header และความลึกของการซ้อน และให้ขีดจำกัดเหล่านี้ครอบคำขอที่ไม่มีความยาว Content-Length ที่ใช้ได้ด้วย เพราะเป็นช่องที่การโจมตีใช้หลบ post_max_size [1] ในคอนเทนเนอร์ให้ใช้ขีดจำกัดของ cgroup เป็นเส้นแบ่งเรื่องความพร้อมใช้งาน และตั้งนโยบายให้ฆ่าเฉพาะ worker ที่มีปัญหา ไม่ใช่ทั้งคอนเทนเนอร์ [1] และ ห้ามใช้ RLIMIT_AS หรือ RLIMIT_DATA แทน เพราะ PHP ระบุว่าค่าเหล่านี้ทำให้เกิดการจัดสรรหน่วยความจำล้มเหลวซึ่งเป็นตัวจุดชนวนเส้นทางที่เปราะบาง [1] สำหรับ CVE-2026-109619 (ช่องสถานะค้าง) ตั้ง session.upload_progress.enabled=0 แล้วรีสตาร์ต worker ทุกตัว โดยต้องตั้งผ่าน php.ini หรือคอนฟิก FPM หรือเซิร์ฟเวอร์ที่ทำงานก่อนการอ่านคำขอ ห้ามพึ่ง ini_set() หรือ .user.ini [1] มาตรการนี้ปิดเส้นทาง session ที่ยืนยันแล้ว แต่ไม่ได้ปิดทุกรูปแบบ [1] ถ้าคุณใช้ FPM และรับภาระเรื่องประสิทธิภาพได้ ประกาศแนะนำ pm.max_requests=1 ด้วย เพื่อไม่ให้ worker ตัวเดิมรับคำขอถัดไป ซึ่งตัดโอกาสที่สถานะจะค้างข้ามคำขอ [12] และให้ลบการตั้งค่า ini ที่ไม่ถูกต้องหรือเลิกใช้แล้วซึ่งถูกใช้ต่อคำขอและทำให้เกิดข้อความเตือนก่อนการเริ่มต้นคำขอ เพราะการซ่อนข้อความด้วย error_reporting, display_errors หรือ @ ไม่ช่วย [1] ข้อสุดท้ายที่ประกาศระบุคือให้แก้ fatal error และการหมดเวลาทำงานที่ผู้โจมตีกระตุ้นได้จริง ทั้งใน callback การอัปโหลดหรือนำเข้า และช่วงเก็บกวาดหลังจบคำขอ [1] ตัวอย่างการตรวจว่าค่ามีผลจริง วิธีที่ตรงที่สุดคือวางไฟล์ probe ชั่วคราวในเว็บที่ใช้ FPM หรือ mod_php แล้วเปิดผ่านเบราว์เซอร์ <?php var_dump(ini_get('memory_limit'), ini_get('post_max_size'), ini_get('upload_max_filesize'), ini_get('session.upload_progress.enabled')); เปิดดูแล้วลบไฟล์ทิ้งทันที เพราะไฟล์นี้เผยค่าตั้งของเซิร์ฟเวอร์ให้ใครก็ได้ที่เปิดเจอ ส่วนคำสั่งนี้ใช้ดูค่าอ้างอิงของ PHP ฝั่ง command line เท่านั้น ไม่ใช่ค่าที่เว็บใช้จริง php -i | grep -E "memory_limit|post_max_size|upload_max_filesize" ตรวจว่าโดนไปแล้วหรือยัง CISA แนะนำให้เฝ้าดูโปรเซส worker ของ PHP ที่ไปเรียกเชลล์หรือดาวน์โหลดเครื่องมือ [2] ถ้าพบโปรเซสที่ไม่มีเหตุผล ให้แยกเครื่องออกจากเครือข่ายก่อน แล้วค่อยเก็บหลักฐาน รายการที่ผมแนะนำให้เก็บเป็นข้อเสนอของผมเอง ไม่ได้มาจากประกาศไหน คือ access log ย้อนหลังอย่างน้อย 24 ชั่วโมง ซึ่งเป็นช่วงที่ครอบทั้งก่อนและหลังแพตช์ออก, log ของ PHP-FPM, รายการไฟล์ที่ถูกแก้ในโฟลเดอร์เว็บ และรายการงานตามเวลาที่ถูกเพิ่มใหม่ จากนั้นจึงค่อยหาสิ่งที่ผู้โจมตีมักทิ้งไว้ คือไฟล์ที่รันคำสั่งได้ ซอร์สโค้ดที่ถูกเติมบรรทัดแปลก ๆ และบัญชีผู้ใช้ที่เพิ่มขึ้นมาใหม่ และเพราะช่องโหว่นี้ยังอ่านหน่วยความจำได้ [6] ถ้าคุณสงสัยว่าโดน ควรถือว่ารหัสผ่าน โทเคน และคีย์ที่อยู่ในเครื่องนั้นรั่วแล้ว และหมุนเวียนค่าเหล่านี้ ผมเปิดอะไรเองบ้าง และอะไรที่ยังไม่ได้เปิด ผมเปิดประกาศบน php.net อ่านเต็มฉบับ รวมถึงส่วนมาตรการลดความเสี่ยงและรายการ source backport [1] ผมเปิดบันทึก CVE ทั้งสองตัวบน NVD และตรวจช่วงเวอร์ชันที่ระบุไว้จริง [5] ผมเปิด advisory สองฉบับบนคลัง php-src ฉบับแรก GHSA-w8hw-w9fx-j79w ว่าด้วยตัว OOM อีกฉบับ GHSA-6wmf-4rv5-p3rp ว่าด้วยสถานะค้าง แล้วอ่านสรุปทางเทคนิคของทั้งคู่ [4] [12] ผมเปิดประกาศของ CISA ฉบับวันที่ 21 ตุลาคม อ่านข้อแนะนำครบทุกข้อ [2] ผมเปิดงานของ Wiz Research อ่านข้อความเรื่องขอบเขตที่ย้อนไปถึง 5.4 และเรื่องการอ่านหน่วยความจำ [6] ผมตรวจ pull request ของ docker-library/php และยืนยันว่า ถูกรวมเมื่อวันที่ 21 ตุลาคม เวลา 14:19 UTC [10] สิ่งที่ผมยังไม่ได้ตรวจ ผมไม่ได้ทดสอบช่องโหว่หรือแพตช์ด้วยตัวเอง และไม่มีแล็บให้ทดสอบ ผมไม่ได้ตรวจว่าโฮสติ้งรายใดในประเทศไทยอัปเดตแล้วหรือยัง และผมไม่ได้ยืนยันตัวเลข "70 เปอร์เซ็นต์ของเว็บทั่วโลก" ที่ Wiz ใช้ เพราะเป็นตัวเลขของผู้ให้บริการรายนั้น ไม่ใช่สถิติที่ผมวัดเอง คำถามที่ผมอยากฝากถึงคนดูแลระบบ ถ้าคุณดูแลเว็บหลายสิบเว็บ คำถามที่ไม่ใช่ "แพตช์แล้วหรือยัง" แต่คือ "คุณรู้หรือไม่ว่าทั้งหมดมีกี่เว็บ และรุ่นไหนบ้าง" เพราะในคืนที่แพตช์ออก สิ่งที่ทำให้คนแพตช์ไม่ทันมักไม่ใช่ความยากของการติดตั้ง แต่คือการไม่รู้ว่ามีอะไรอยู่ในมือ แหล่งอ้างอิง [1] The PHP Development Team, "Security advisory: Critical remote code execution vulnerabilities, update now", php.net News Archive, 21 ต.ค. 2026 (8.5.12 · 8.4.27 · 8.3.36 · 8.2.35 · SAPI ที่เสี่ยง · รายละเอียดทั้งสอง CVE · source backport สำหรับ 7.4, 8.0, 8.1 · มาตรการลดความเสี่ยง memory_limit, post_max_size, session.upload_progress, fatal_error_backtraces · ห้ามใช้ RLIMIT_AS/RLIMIT_DATA). php.net [2] CISA, "Critical Vulnerabilities in PHP Require Immediate Patching", 21 ต.ค. 2026 (แนะนำให้อัปเดตเป็น 8.5.12, 8.4.27, 8.3.36 หรือ 8.2.35 · ยังไม่พบการโจมตี ณ เวลาเผยแพร่ · แนะนำ inventory · ให้ระบบที่ใช้ 8.1 หรือเก่าออกออฟไลน์จนกว่าจะแพตช์ · WAF ช่วยได้บางส่วน · เฝ้าดู PHP worker เรียกเชลล์). cisa.gov [3] Ionut Arghire, "PHP2Shell Patches Land as First Exploitation Attempts Hit Sensors", SecurityWeek, 21 ต.ค. 2026 (watchTowr เห็นความพยายามโจมตีราวเวลาที่แพตช์ออกแต่ยังไม่มีรายสำเร็จ · คำพูดของ Jake Knott · Hadrian เห็นการโจมตีวงกว้างและเส้นทาง session upload progress · Patchstack, Cloudflare, Vega เห็นความพยายามโจมตี · ขอบเขตย้อนถึง 5.4 · การอ่านหน่วยความจำ). securityweek.com [4] PHP Security Team (bukka), "RCE via OOM corruption", GHSA-w8hw-w9fx-j79w, 21 ต.ค. 2026 (affected: ก่อน 8.2.35 · 8.3.0 ถึงก่อน 8.3.36 · 8.4.0 ถึงก่อน 8.4.27 · 8.5.0 ถึงก่อน 8.5.12 · patched: 8.2.35, 8.3.36, 8.4.27, 8.5.12 · กลไก OOM ผ่าน multipart · mod_php เรียก shutdown โดยไม่เงื่อนไข · FPM ออก child เมื่อ startup ล้มเหลว · FrankenPHP และ LSAPI). github.com/php/php-src/security/advisories/GHSA-w… (คู่แฝดของ CVE-2026-109619 คือ GHSA-6wmf-4rv5-p3rp) [5] NIST, National Vulnerability Database, CVE-2026-109618 และ CVE-2026-109619, เผยแพร่ 21 ต.ค. 2026 เวลา 14:17 UTC (CVSS v4.0 9.2 · CVSS v3.1 9.8 · ช่วง CPE: ก่อน 8.2.35, 8.3.0 ถึงก่อน 8.3.36, 8.4.0 ถึงก่อน 8.4.27, 8.5.0 ถึงก่อน 8.5.12). nvd.nist.gov · nvd.nist.gov [6] Sagi Tzadik และคณะ, "PHP2Shell: AI uncovers critical RCE vulnerabilities affecting 70% of the Internet", Wiz Blog, 21 ต.ค. 2026 (PHP เกือบทุกรุ่นย้อนถึง 5.4 มีปัญหาอย่างน้อยหนึ่งตัว · อ่านหน่วยความจำโปรเซสได้ · ใช้โมเดล AI ช่วยค้นหา · ตัวเลข 70 เปอร์เซ็นต์เป็นของผู้ให้บริการรายนี้). wiz.io [7] The PHP Group, "Supported Versions", php.net, สืบค้น 22 ต.ค. 2026 (8.2 หมดช่วงสนับสนุนความปลอดภัย 31 ธ.ค. 2026 · 8.3 ถึง 31 ธ.ค. 2027 · 8.4 ถึง 31 ธ.ค. 2028 · 8.5 ถึง 31 ธ.ค. 2029). php.net [8] php-src, แบรนช์ source backport, GitHub, สืบค้น 22 ต.ค. 2026 (PHP-7.4-CVE-2026-109618-109619 · PHP-8.0-CVE-2026-109618-109619 · PHP-8.1-CVE-2026-109618-109619). github.com/php/php-src/branches/all [9] The PHP Group, "Unsupported Branches", php.net, สืบค้น 22 ต.ค. 2026 (7.4 หมด 28 พ.ย. 2022 · 7.3 หมด 6 ธ.ค. 2021 · 5.6 หมด 31 ธ.ค. 2018). php.net [10] docker-library/php, "Update to 8.5.12, 8.4.27, 8.3.36, 8.2.35", pull request 1694, รวมเมื่อ 21 ต.ค. 2026 เวลา 14:19 UTC. php#1694 [11] Sansec Forensics Team, "PHP2Shell: critical RCE and memory disclosure in PHP", Sansec Threat Research, 21 ต.ค. 2026 (กระทบเว็บเซิร์ฟเวอร์ที่รัน PHP 5.4 ขึ้นไป · โค้ดเปราะบางมีมาตั้งแต่ 5.4.0 ปี 2012 · ยืนยัน RCE แบบไม่ต้องยืนยันตัวตนบน Magento 2.4.9 และแอป PHP อีกสิบตัว · mod_php และ FPM ได้รับผลทั้งคู่ · ค่าตั้งเริ่มต้นก็อยู่ในข่าย · การอ่านหน่วยความจำเกิดได้แม้แอปไม่เรียก session_start). sansec.io [12] PHP Security Team (bukka), "RCE via stale global state", GHSA-6wmf-4rv5-p3rp, 21 ต.ค. 2026 (affected: ก่อน 8.2.35 · 8.3.0 ถึงก่อน 8.3.36 · 8.4.0 ถึงก่อน 8.4.27 · 8.5.0 ถึงก่อน 8.5.12 · patched 4 รุ่น · กลไกสถานะค้างข้ามคำขอใน worker เดียวกัน · มาตรการ session.upload_progress.enabled=0 และ fatal_error_backtraces=0). github.com/php/php-src/security/advisories/GHSA-6…

  5. Bluesky · · @trnck.dev

    :obama_phew: ``` # php -v PHP 8.5.12 (cli) (built: Oct 21 2026 15:49:40) (NTS) Copyright (c) The PHP Group Built by docker-library/php Zend Engine v4.5.12, Copyright (c) Zend Technologies with Zend OPcache v8.5.12, Copyright (c), by Zend Technologies ```

    1 like
  6. The hero gets the bill Last night, at about half six, I'd finished work for the day and was settling in for an hour or two on a new side project (a heads-up display for keeping track of the twenty or so agent sessions I seem to run these days, but that's a post for another time). My phone went. A friend, a fellow Scout leader and a DevOps sort, had forwarded me an email he'd just had from the Scouts. The UK's National Cyber Security Centre had put out guidance about a critical flaw affecting some websites, and the Scouts were asking every volunteer who looks after a group, district or county website to check whether it runs PHP and, if it does, to patch it or take it down. Underneath, he'd written: "I think this is time for thephpboyscout to shine 🙂" I laughed, told him that, looking at the news, smarter minds than mine had already fixed it, and went back to my side project. A second friend sent me The Register's write-up a little later and I didn't even open it. I don't run PHP in anything these days, it had been a long day, and the shiny new toy was a lot more interesting. My whole reaction was a shrug and a "here we go again, everyone bashing on PHP". Then this morning, sat in bed with a coffee and Hailey, doing the morning doom scroll, my feed was wall to wall with it. Reels, TikToks, people talking to camera with that slightly-too-wide-eyed look. And it slowly dawned on me that this wasn't the usual PHP-shaped news story at all... this was a real one. What stopped me in my tracks was the reaction. Sites were taking themselves offline. Two bugs and a fire alarm If you've somehow managed to miss it, here's the short version. Two vulnerabilities, published together on Wednesday as CVE-2026-109618 and CVE-2026-109619, both rated 9.2 out of 10, both allowing someone with no account and no credentials to run their own code on a PHP server. Someone christened them "PHP2Shell", because of course they did, and they got a logo and a website before most people had read the advisory. So, PHP lets you cap how much memory a single request can use, the memory_limit setting you've almost certainly bumped at some point to stop an import script falling over. When a request goes over that limit, PHP doesn't hand back a polite error and tidy up, it pulls the fire alarm and legs it out of whatever it was in the middle of (in C terms it uses longjmp, which is about as subtle as it sounds). If it happened to be halfway through building something when the alarm went, that half-built thing gets left lying about, and the clean-up crew that runs at the end of the request later trips over it and treats it as finished. Get the timing right with a carefully stuffed upload and you get to decide what the clean-up crew trips over. The second bug is a cousin of the first: a fatal error leaves a pointer to the previous request's memory lying around for the next request on the same worker to pick up. Under Apache's mod_php the first one fires before a single line of your application runs, with default settings. So it doesn't matter how good your WordPress plugins are, or how carefully your framework validates input... this lives underneath all of that. The fix shipped in PHP 8.5.12, 8.4.27, 8.3.36 and 8.2.35, and it's a big one: 300 files and nearly eleven thousand added lines, getting on for half of them tests, which changes how PHP runs out of memory altogether. And the advice from the PHP project, the agencies and every explainer on my feed boiled down to the same thing: there's no setting that makes this safe, so upgrade. (If you want to check my working on any of what follows, I've put the research notes up alongside this post, warts and all.) Three facepalms in twenty-four hours I'd love to tell you the disclosure went smoothly. The PHP Foundation's own write-up says it went well right up until two days before release, and then the wheels came off one at a time. On Tuesday afternoon the two CVE numbers started circulating on forums and social media, complete with the wrong release time and a wrong severity score of 10.0. Someone with early access couldn't keep it to themselves. That's facepalm number one, and it's negligence, plain and simple. PHP responded by bringing everything forward a day. That same evening Calif, one of the security firms that had reported the bugs, accidentally published a video of their proof of concept working against a string of real applications (with a dancing anime character in the corner, which one Hacker News commenter assured everyone is "a sign of credibility" in some circles). It was taken down, but copies were doing the rounds soon after. Facepalm number two, and that one's just sloppy. And then, at 07:41 UTC on Wednesday, more than six hours before the coordinated release, Chainguard published container images with the fix already built in. Facepalm number three! That's the one that really got my blood up when I first read it, so I went digging. The fix commit was written days earlier, but going by the git history it only landed on PHP's public branches at 14:06 UTC on Wednesday, about half an hour after the advisories went live. (Git timestamps aren't proof of when something was pushed, so take that as "no sign of it in public any earlier" rather than gospel.) The CVE leak and the video gave away that something was coming and roughly where to look. Chainguard's images gave away the patched code itself, as binaries anyone can diff against the old ones, six and a half hours before the source was public. With AI in the mix, six hours is an eternity. Now, in fairness, Chainguard's CEO has his side of it. He says he made the call once exploits were being reported in the wild, and he told The Register that his team had found the same bugs independently, with an AI harness, and that he wouldn't do anything differently. I get why. The reports flying about at the time turned out to be reports of attempts (more on that below), but if you really believe people are being hit, sitting on a fix feels indefensible. And later that same evening, an account called "The Chainguard Team" dropped $50,000 into the PHP Foundation's collective, and that took a fair bit of the wind out of my sails. A case of too little, too late, perhaps, but it's not nothing. What still frustrates me is the coordination. If it was right for one distributor to ship early, it was right for all of them, and Docker Hub makes that point better than I can. The official PHP image on Docker Hub has over 1.38 billion pulls (some of them mine). It's probably the single biggest way PHP gets into the containerised world, and as far as I can tell it wasn't in the early circle at all. The update was opened by a community contributor ten minutes after the advisories went public, then sat in the usual review and build pipeline, then hit a deploy glitch that left the tags visible on Docker Hub with no amd64 image behind them. People were building their own from source and asking to go to bed. It was close to three hours before most folk could pull a patched image. So the company that sells hardened images got the fix in advance, and the free default that so much of the containerised PHP world builds on got it at the same moment as the attackers did... and then dawdled! Smarter minds, and not very many of them When I told my friend that smarter minds than mine had already fixed it, I meant it. I've met a fair few of the people who work on PHP over the years at conferences and the like, and they're far more skilled and capable than I am (I'm not being modest, they really are). My grand contribution to the PHP project is helping write some tests at a couple of hackathons. So the fix being out before I'd even heard of the problem is about the order I'd expect. What I hadn't thought about was how few of them there are. The fix commit has five authors. Looking at the history of the engine core itself, about five people account for half of this year's commits (commits aren't the same thing as work, I know, but it gives you an idea). The person coordinating the security effort across the wider ecosystem is in a six-month post paid for by a grant. The maintainer of a volunteer package repository that a lot of Red Hat-family servers rely on was on holiday, and php.net's own advisory had to tell people to switch away from it because it "will not have updates today". And by teatime Mastodon was busy passing round the Patreon link for the man whose PHP packages a great many Debian and Ubuntu servers pull from. And the inbox isn't getting any emptier. PHP's own security advisories went from 14 in the whole of 2025 to 29 so far this year, with ten weeks still to run, plus over a hundred reports since July that turned out to be duplicates, invalid or impossible to reproduce. Someone from that same handful still had to open and read every one of them. The Foundation hasn't hidden any of this. Its write-up says, in as many words, "We won't pretend otherwise: the delay was a structural failure, caused by both the security team's decision process and its lack of resources". It explains that the first signs of the memory problem turned up back in 2024, when a developer the Foundation pays was fixing something else from an external audit, and that the security team, working by consensus, couldn't agree which of several imperfect fixes to ship until there was a proof that it could be exploited. They're moving to majority decisions so that doesn't happen again. And that brings me to a coincidence I had no hand in at all. This morning another post of mine went out, written weeks ago and sat in the queue, arguing that "blameless" was only ever meant to make it safe to tell the truth, and that the truth usually starts with your own share. I couldn't have asked for a better worked example if I'd tried. The PHP Foundation named its own failure first, plainly, and then named everyone else's. That's a charming coincidence on the scheduling, and it hits home all the same. If you've read the comments on a few forums today you'll know not everyone agrees they handled it well (the engineers' corners of the internet are a lot harder on them than the sysadmins'), but I think they responded about as well as anyone could have, and they've been open about the parts they got wrong. Every hero gets a bill There's a scene early on in The Incredibles that I keep coming back to. The supers are beloved. They stop the robbery, catch the villain, save the day... and then the lawsuits start. A man who was trying to jump off a building sues because he didn't want to be saved. The train passengers want compensation for their whiplash. The bill for all that heroism lands, the public turns, and the heroes end up in hiding. My first reaction to the AI part of this story was that AI was the hero, and I still think it is. Calif, OpenAI and Wiz found these flaws with frontier models in a matter of weeks, after people had been reading that code for well over a decade. That's two critical bugs found and fixed by people on our side of the fence, before (as far as anyone can yet show) anyone used them to do real harm. That's a rescue. But the bill came with it. AI made finding these bugs fast, and it made exploiting them fast too. Trail of Bits wrote working exploits for a stock MediaWiki install and their CEO said the first one took about four hours, start to finish, while being clear that it "still requires expertise, even when you're being aided by an LLM". What used to be weeks of tedious work by a rare specialist is now an afternoon for a capable one with a model at their elbow. I wrote about curl's bug bounty back in May and argued that AI had made the cheap half of security work free and left the expensive half where it was. This is the same story a little further down the line. Finding is cheap now, and fixing is still five people and a grant. That's also why, a couple of years ago, I'd have called taking your site offline over a PHP bug a massive overreaction, and today I don't. A bad actor with a model can turn an advisory into a working attack faster than most of us can get a change approved. And a dull-looking site is rarely the target in itself. It's the first door. Leak a bit of state and get code running, and that site is a foothold into the next system, and the one after that, until you reach something that matters. We've already watched a frontier model climb out of what its own makers thought was a closed sandbox to get at what it wanted. Flaws like these make that kind of hopping trivial, and that's before you get to whatever personal data leaks out along the way and turns up later in a very convincing phishing email. So I think the governments got this one right, even if it was drastic. The BSI, the Dutch NCSC, France's ANSSI, the US NSA and our own NCSC (which reached me via the Scouts!) all told people to take sites down if they couldn't patch. Japan's prime minister posted an "urgent request" late at night telling organisations to check their sites, and Japanese Wikipedia's page on PHP went from 66 visits the day before to over a hundred thousand. On one volunteer-run tracker the median site went dark for about four and a half hours, the Dutch parliament and Edinburgh council among them. And as of this morning, despite one headline talking about millions of exploit attempts, I can't find anyone who has publicly confirmed a single successful compromise. One threat-intelligence group quietly took its "exploited in the wild" label off the story early this morning, on the grounds that sprays against targets aren't proof of anyone getting in. That's good news, but it's only a day old. The question that bothers me most is the one I don't think anyone can answer. Amazon's honeypots caught an exploitation attempt on the 17th, four days before anyone outside the circle was meant to know, and the root of the problem has been documented in public for over twenty years. How many people knew about this, and used it, before any of us did? Hopes of the father Whenever PHP has a bad day, the same crowd turns up. PHP is a joke, PHP is dead, just use anything else. You've seen the threads, I'm sure. I'll grant that PHP has made some questionable decisions in its time, and plenty of what people call technical debt in the language is just the scar tissue of it growing up in public. But Rasmus Lerdorf put it together in 1994 to make web pages a bit more interactive, which makes it thirty-two years old... older than some of the people sneering at it! It's still sat at number twelve on TIOBE this month (one place behind Go, my current favourite, and somewhat bafflingly ahead of COBOL at sixteen, which makes me think I need a better yardstick than TIOBE). And it got me out of a run of humdrum menial jobs and into the career I love. It's been a long-distance relationship for a while now, but the respect has never gone anywhere. Some people will call PHP2Shell the sins of the father. I'd call it the hopes of the father. Stefan Esser described this very class of bug in July 2004, interrupting PHP at an unsafe moment by running it out of memory, and rated it critical. In 2019 a closely related bug report came in, and the maintainer looking at it wrote that "Allocation failure strictly speaking is not a crash", and the fix that followed dealt with that report and moved on. In 2024 the security team saw the first signs again, and with no known path to remote code execution, couldn't settle on a fix. Each one of those calls was reasonable when it was made. The people who built PHP built it as well as they could, with what they knew, for the world in front of them. Nobody has a crystal ball. I don't think any of those calls were wrong about the bug... where they came unstuck was the price. Each one was a bet that turning this into a working exploit was too much effort for too little reward, and for twenty years that bet paid off. The bug didn't change in 2026, but what it costs to exploit it certainly did. And that's the part of this story that isn't really about PHP at all. I'd wager most codebases that have been around long enough have a drawer of bugs that someone marked as "not exploitable in practice", and in practice was always a statement about cost. Java, the C underneath half the languages we use, and yes, my own estate. I've got private bug reports sat in a tracker right now, some marked exploitable and some marked not, and triaging them is my job and nobody else's. Reading about PHP's 2019 bug this morning, I suspect a few of mine need re-reading with fresh eyes, because the price on all of them dropped this year too. Patch now, they said So, to the advice everyone's been shouting for two days, mine included. Upgrade. It's the right advice, but it's also advice that a huge chunk of the PHP web can't simply take. WordPress publishes its own statistics on which PHP versions its installs run, and as of this morning 35.8% of them are on a version of PHP the PHP project no longer releases fixes for. PHP 7.4 alone is about one in six. Another 23.7% are on 8.2, which stops getting security fixes on the 31st of December. So by New Year, unless an awful lot changes very quickly, nearly sixty percent of WordPress will be running a PHP with no upstream fixes at all. W3Techs' survey of the wider PHP web lands in the same place by a different route, at about 48%. The PHP security team did go above and beyond here, publishing minimal source backports for 7.4, 8.0 and 8.1 so that people building from source weren't left with nothing, and the LTS vendors and Linux distributions covered a lot of servers. Debian and Ubuntu had packages out within half an hour of the advisories, which is what the embargo was for. But for a site two major versions behind on shared hosting, "just upgrade" is a project, and a fiddly one at that: a jump across breaking changes, an audit of plugins that may not have been touched in years, and a theme that might fall over the moment you look at it. And WordPress itself still says it works on 7.4, even while warning that it's past end of life. So who runs that project for the Scout group's website? Or the parish council, or the little charity, or the volunteer who looks after the cricket club on a Tuesday night? Scouting Nederland's site was dark for an hour and three quarters on Wednesday. The Scouts here were emailing their volunteers asking them to check. I've stared, hard, at more than one company still running Java 8 in production, and I'll keep doing it. But a big company on Java 8 has made a choice, and the volunteer with the group website mostly didn't know there was one to make. Time for the PHP Boy Scout to shine So my friend was half right. It was time for the PHP Boy Scout to shine... I just think it's a lot less about knowing PHP and a lot more about the old Baden-Powell line this blog's motto is borrowed from, the one about leaving things a little better than you found them. The smarter minds fixed PHP in a day. The heroes got the applause, and the bill went to five people, a few volunteers on holiday, and everyone who now has to find out what version of PHP their club website is running. As for me, I've a drawer of my own to go through. --- Originally published at phpboyscout.uk on 22 October 2026.

  7. github.com/docker-library/php/actions/runs/396158… 大急ぎでパッチを当てたコンテナがビルドされるのをみんなでみまもろう

  8. Habr · · @opium

    Две критические RCE в PHP: что обновлять и как проверить за минуту 21 октября PHP выпустил внеплановые релизы 8.5.12, 8.4.27, 8.3.36 и 8.2.35. Они закрывают две уязвимости, которые по описанию проекта позволяют выполнить код на сервере без аутентификации: CVE-2026-109618 и CVE-2026-109619. У обеих CVSS 4.0 равен 9.2, severity critical. Ниже: кого это касается, как проверить свою версию за минуту, как обновиться и что делать, если обновиться прямо сейчас нельзя. Кого касается По сводке на php.net, под риском все установки PHP, которые обслуживают веб-запросы: PHP-FPM, Apache с mod_php, php-cgi, FrankenPHP и LiteSpeed. Выше всего риск у mod_php: проект пишет, что для него показан эксплойт, где неаутентифицированный запрос срабатывает до выполнения кода приложения. Уязвимы все версии ниже 8.2.35, 8.3.36, 8.4.27 и 8.5.12. PHP 8.1 и старше проект больше не обновляет. Для 7.4, 8.0 и 8.1 команда безопасности выложила минимальные бэкпорты исходников в ветках php-src (PHP-7.4-CVE-2026-109618-109619 и аналогичные для 8.0 и 8.1). Дистрибутивы и LTS-вендоры могут дать свои бэкпорты, это стоит уточнить у них. Что именно исправлено Если коротко, по описаниям из advisory: CVE-2026-109618 (GHSA-w8hw-w9fx-j79w): обработка нехватки памяти может прервать PHP, пока внутренние данные запроса инициализированы не до конца, и очистка запроса примет их за валидные. CVE-2026-109619 (GHSA-6wmf-4rv5-p3rp): внутреннее состояние запроса может пережить освобождение своей памяти, и следующий запрос, который обработает тот же воркер, воспользуется устаревшим состоянием. Для FPM картина менее ясна: анализ исходников считает его уязвимым, но полного эксплойта для FPM проект не показывал. Это не повод откладывать обновление. В ChangeLog обе правки записаны одной строкой в разделе Core: «Avoid state corruption via bailout». Проверка за минуту Важно проверить именно ту сборку, что отвечает на веб-запросы. CLI и FPM в одном контейнере или на одном хосте могут оказаться разными версиями. php -v php-fpm -v # версия, которая реально обслуживает веб docker exec <контейнер> php -v # для контейнеров php -r 'var_dump(version_compare(PHP_VERSION, "8.4.27", ">="));' # подставьте свою ветку sourcecraft.dev Пороги: 8.5.12, 8.4.27, 8.3.36, 8.2.35. Всё, что меньше, нужно обновлять. Как обновиться Пакеты дистрибутива. Дистрибутивы и LTS-вендоры получили патчи заранее, поэтому первым делом посмотрите обновления у своего вендора. Отдельно php.net предупреждает: репозиторий rpms.remirepo.net сегодня обновлений не получит, тем, кто на нём, рекомендуют перейти на пакеты дистрибутива или собирать из исходников. Официальные образы Docker. На 15:00 UTC 21 октября в php:* на Docker Hub были только релиз-кандидаты. Я проверил это сам в 15:20 UTC: $ for t in 8.5-cli 8.4-cli 8.3-cli 8.2-cli; do docker run --rm --pull always php:$t php -r 'echo PHP_VERSION,"\n";' done 8.5.11 8.4.26 8.3.35 8.2.34 sourcecraft.dev Все четыре версии ещё уязвимые. Исправление в репозитории docker-library/php уже смержено (коммит e3eaff8), так что образы появятся с обычной задержкой. Если ждать не хочется, образ можно собрать самим из Dockerfile этого репозитория, подставив исправленную версию и её SHA256 с php.net. Наши готовые образы. Мы собрали такой набор: stufently/php-patched-images (MIT), образы лежат в ghcr.io/stufently/php-patched-images. Что внутри: PHP собирается из исходников по Dockerfile docker-library/php с коммита e3eaff8; тарбол проверяется по SHA256 с php.net, база — Debian 13 trixie-slim; ветки 8.5, 8.4, 8.3 и 8.2, варианты cli, fpm и apache, архитектуры amd64 и arm64; сборка раз в неделю, чтобы подтягивать обновления Debian; перед публикацией CI проверяет версию, список расширений и реальный запрос через FPM и Apache; теги 8.5-fpm, точные 8.5.12-fpm-web и датированные неизменяемые вида 8.5.12-fpm-web-YYYYMMDD; профили с расширениями: web (WordPress, OpenCart, Joomla, Drupal), app (Laravel, Symfony, воркеры, плюс composer), dev (с xdebug, не для прода). Переход обычно сводится к замене одной строки и пересборке: FROM ghcr.io/stufently/php-patched-images:8.5-fpm sourcecraft.dev Проверка: docker run --rm ghcr.io/stufently/php-patched-images:8.5-cli php -v sourcecraft.dev После любого обновления перезапустите все воркеры, иначе старые процессы продолжат работать на прежнем коде. Если обновиться нельзя прямо сейчас php.net подчёркивает: единственное полное решение — обновление. Меры ниже закрывают отдельные пути, но установку безопасной не делают. Для CVE-2026-109618: memory_limit=-1, желательно так, чтобы приложение не могло переопределить его (php_admin_value в пуле FPM или конфиге Apache); проверьте, что ни пул, ни каталог, ни приложение не ставят конечный лимит обратно; небольшой post_max_size: 8M, если загрузок файлов нет, и 32M, если есть; upload_max_filesize держите ниже него; лимиты на уровне веб-сервера или прокси: размер запроса после декодирования, число полей, частей multipart, заголовков и глубина вложенности, причём и для запросов без пригодного Content-Length; лимит контейнера или cgroup как граница доступности, лучше с политикой, которая убивает только затронутый воркер; RLIMIT_AS и RLIMIT_DATA для этого не подходят. Для CVE-2026-109619: session.upload_progress.enabled=0 в php.ini, пуле FPM или конфиге сервера, который применяется до разбора запроса, и перезапуск всех воркеров; ini_set() и .user.ini для этого не годятся; на PHP 8.5 дополнительно fatal_error_backtraces=0; уберите устаревшие или невалидные настройки, которые применяются на каждый запрос и выводят диагностику до инициализации (скрытие диагностики через error_reporting, display_errors или @ не помогает); исправьте фатальные ошибки и таймауты, до которых может дотянуться злоумышленник, в том числе в колбэках, обработке загрузок и импорта. Итог Выясните, какая сборка PHP отвечает на веб-запросы, и сравните её с порогами выше. Обновитесь через пакеты вендора, а в Docker — собственной сборкой или готовым образом, и перезапустите все воркеры. Пока не обновились — временные меры и лимиты на прокси, помня, что это лишь снижение риска. Первоисточники: сводка на php.net, ChangeLog, advisory GHSA-w8hw-w9fx-j79w и GHSA-6wmf-4rv5-p3rp, NVD CVE-2026-109618, NVD CVE-2026-109619, CERT-EU 2026-018.

  9. Bluesky · · @byte.cx

    halbes internet gammelt auf einem PR rum, war klar php#1694

    6 likes
  10. Hacker News · · on PHP 8.2.35 · andrin

    They even committed the fixed version to the repo, but it seems no images where pushed: github.com/docker-library/php/commit/e3eaff845f7a… Edit: Seems like GitHub has issues with merging PRs: official-images#22541

Latest stargazers

The last 10 distinct accounts we observed this year.

Most active participants

PR, issue, comment & review events in the past year.

Packages

No packages found.

README badges

Embed a badge in your README or website.

Live mentions · last 30 days
docker-library/php mentions in the last 30 days