composer

Stars and mentions

Last 30 days, Oct 5 – Nov 3

GitHub stars124
mentions5
036912Oct 5Oct 19Nov 3
UTC days · repositories composer owns2 repositories

Package downloads

No package download history available yet.

Top repositories

composer’s repositories ranked by new forks, as on trending.

Loading

Contributes to

Repositories outside composer’s account where composer opened or reviewed pull requests in the past 365 days.

Who noticed composer

Everyone who starred or forked composer’s repositories since the archive began in 2011.

Notable accounts

Ordered by the stars their own repositories have received.

Biggest fans

Accounts that starred the most of these repositories.

Breakout weeks

Each repository’s best week of new stars, with the release published around it.

Mentions

5posts
Nov 40 posts
  1. Composerのdump-autoloadは--no-devの指定をどう判断しているのか はじめに Composerで本番環境向けに依存パッケージをインストールするとき、--no-devオプションを指定することがあります。 composer install --no-dev そのあとに、次のコマンドを実行したとします。 composer dump-autoload dump-autoloadコマンドには--no-devを指定していませんが、開発用のオートロード設定(autoload-dev)は除外されたままでした。 なぜ、このような動作なるのか気になったので、Composerの公式ドキュメントとソースコードを確認してみました。 環境 PHP 8.5.12 Composer 2.10.3 公式ドキュメントを確認する まず、Composerの公式ドキュメントを確認します。 getcomposer.org dump-autoloadコマンドの--dev及び--no-devオプションには次の説明があります。 Composer will by default infer this automatically according to the last install or update --no-dev state. どちらも、最後のinstallまたはupdateで指定された--no-devの状態から自動的に判断される、と書かれています。 つまり、dump-autoloadコマンドは--dev及び--no-devオプションが指定されていない場合、直前の状態で判断しているようです。 直前の状態で判断とは?この辺りはソースコードから読み解いていく方がよさそうです。 ソースコードを確認する Composerのソースコードを確認します。 dump-autoloadコマンドのDumpAutoloadCommandクラスの処理を順番に追いかけていくとAutoloadGeneratorクラスのdump()メソッドに次の処理があります。 github.com/composer/composer/blob/2.10.3/src/Comp… この処理を見ていきます。 1. devModeが未指定か確認する if (null === $this->devMode) { 最初に、$this->devModeがnullかどうかを確認しています。 $this->devModeがnullの場合は自動判定に進みます。 null以外の場合、--dev及び--no-devが明示的に指定されているため、自動判定の処理には入りません。 この$this->devModeに値を設定するのは、DumpAutoloadCommandクラスで行なっています。 github.com/composer/composer/blob/2.10.3/src/Comp… 2. installed.jsonを読み込む // we assume no-dev mode if no vendor dir is present or it is too old to contain dev information $this->devMode = false; $installedJson = new JsonFile($config->get('vendor-dir').'/composer/installed.json'); if ($installedJson->exists()) { $installedJson = $installedJson->read(); if (isset($installedJson['dev'])) { $this->devMode = $installedJson['dev']; } } 次に、vendor/composer/installed.jsonを読み込んでいます。 ファイルの存在確認を行なってから、installed.jsonの devの値を取得しています。 この値が存在する場合、$this->devModeに値を設定しています。 つまり、--dev及び--no-devオプションを指定していない場合は、installed.jsonのdevの値を使って判断していることになります。 installed.jsonのdevにはどんな値が入る? installコマンドを実行するとInstallCommandクラスが動くのでみてみると以下で --no-devオプションを取得し、設定していることがわかります。 github.com/composer/composer/blob/2.10.3/src/Comp… このsetDevModeメソッドを確認してみると引数の型はbool型になっていました。 github.com/composer/composer/blob/2.10.3/src/Comp… つまり、--no-devオプションがあればfalse、なければtrueを設定しています。 ※!$input->getOption('no-dev')と!がついているので意味が逆転します。 このあとの処理を順番に見ていきます。 github.com/composer/composer/blob/2.10.3/src/Comp… github.com/composer/composer/blob/2.10.3/src/Comp… github.com/composer/composer/blob/2.10.3/src/Comp… 最終的な書き込みは以下の場所で行われていました。 github.com/composer/composer/blob/2.10.3/src/Comp… ここまでの間で設定した値は書き換わっていないので、installed.jsonのdevにはbool値が入っていることがわかります。 この値をdump-autoloadコマンドが読み取ることで、開発用のオートロード設定を含めるかどうかが決まるようです。 まとめ dump-autoloadコマンドはinstalled.jsonのdevの値を見て、開発用のオートロード設定を含めるかどうか判断していることがわかりました。 ソースコードを追いかけてみて、またひとつComposerのことが詳しくなれました。

  2. eMudhraの中間CA鍵漏洩、結局なにが問題なのか はじめに 今週、世間ではPHPの重大な脆弱性「php2shell」が大きな話題になっていました。ですがその影で、もう1つエンジニアが対応に追われたことがありました。 HTTPSの証明書を発行している会社のひとつ、eMudhraで問題が見つかりました。証明書を発行するときに使う「秘密の鍵」が、誰でも計算して取り出せる状態になっていたのです。 ただ、業務でOSやランタイム、ライブラリのアップデートの対応をしながら、正直こう思っていました。 - 「証明書を発行する鍵が漏れると、具体的にどういうリスクがあるのかいまいち理解してないなあ」 - 「うちのサイトはeMudhraの証明書を使っていないのに、なぜ対応が必要があるんだろうか」 - 「なんでOSだけでなく、Python、Node.js、Java、Goまで全部上げる必要があるんだっけ」 なので自分の整理も兼ねて調べてわかったことを書き留めます。 :::note info この記事は2026年10月25日時点の公開情報をもとにしています。状況は変わる可能性があるので、最新情報は末尾の一次情報を確認してください。 ::: 対象読者 - 会社でパッチ当てやバージョンアップの対応をしている(または、これからする) - HTTPSや証明書の仕組みはなんとなくしかわからない - 言われたとおりに対応はしたけれど、なぜ必要なのか腹落ちしていない (ですのでTLSや証明書に詳しい人には当たり前で物足りない内容だと思います。) まとめると 1. eMudhraで、証明書を発行するための「秘密の鍵」が誰でも計算できる状態だった。この鍵があれば、どのサイトの証明書でも本物そっくりに作れる 2. 放っておくと困ることは2つある。偽物のサイトを本物だと信じてしまうことと、正しい手続きで作った証明書なのに、そのサイトにつながらなくなること 3. 「どの証明書を信じるか」のリストは、OS、ブラウザ、Python、Node.jsなどがそれぞれ別々に持っている。だから全部アップデートする必要がある 前提知識:証明書の仕組みをざっくり この記事を読むのに必要なところだけ説明します。 証明書は「相手が本物か」を確かめるためのもの HTTPSには大きく2つの役割があります。 - 通信を暗号化して、途中で盗み見られないようにする - つないだ相手が本物のサイトかどうかを確かめる 今回関係するのは2つ目です。どれだけしっかり暗号化していても、相手が偽物なら、偽物と秘密の会話をしているだけです。 相手が本物かを確かめるために使うのが証明書です。サイトは「私は example.com です」と書かれた証明書を見せます。ブラウザやプログラム(以下まとめて「クライアント」と呼びます)は、それを見て相手を確認します。 信頼できる発行元が出した証明書だけを信じる ただ、「私は example.com です」と書くだけなら誰でもできます。そこで証明書には、認証局(CA) という発行元が「このサイトが example.com の持ち主であることを確認しました」という署名を付けています。 運転免許証にたとえるとわかりやすいです。見せられた免許証を信じるのは、自分で作ったカードではなく、公安委員会という信頼できる機関が発行したものだからです。 信じる発行元のリスト(トラストストア) クライアントは「どの認証局なら信じるか」のリストを持っています。これを トラストストア と呼びます。 - リストに載っている認証局が署名した証明書 → 信じる - 載っていない認証局が署名した証明書 → 「この証明書は信用できません」とエラーにする このトラストストアは、後の項でとても大事になります。 ルートCAと中間CAは「本社と支店」 実際の認証局は、2段階以上の構造になっています。会社にたとえると次のとおりです。 | 証明書の用語 | たとえ | 役割 | |---|---|---| | ルートCA | 本社 | トラストストアに載っている。とても大事なので、ふだんは直接証明書を発行しない | | 中間CA | 支店 | 本社から発行の権限をもらい、実際にサイトの証明書を発行する | | サーバー証明書 | 支店が発行した書類 | 各サイトが使う証明書 | ルートCA(本社。トラストストアに載っている) └ 中間CA(支店。本社が「この支店は信頼してよい」と署名している) └ サーバー証明書(example.com の証明書。支店が署名している) クライアントは、サーバー証明書から順に署名をたどります。最後にトラストストアに載っている本社(ルートCA)にたどり着けば、その証明書を信じます。このつながりを 証明書チェーン と呼びます。 秘密鍵は「支店の印鑑」 署名に使うのが 秘密鍵 です。たとえるなら、支店の印鑑です。 ふだん支店は、申し込んできた人が本当にそのドメインの持ち主かを確認してから、印鑑を押して証明書を発行します。 しかし、印鑑そのものが盗まれたらどうなるでしょうか。確認を飛ばして、どのサイトの証明書でも作れてしまいます。しかも押されているのは本物の印鑑なので、クライアントから見ると本物と見分けがつきません。 署名が本物かを確かめるための 公開鍵 は、誰でも見られるようになっています。印影のようなものです。今回の問題は、この公開鍵から秘密鍵を計算できてしまったことでした。たとえるなら、印影を見るだけで印鑑を複製できる状態だったということです。 イメージ図 !スクリーンショット 2026-10-25 18.41.01.png 何が起きたのか - 2025年4月、eMudhraが中間CAの鍵を作るときに、手順とコードの不具合で非常に弱い秘密鍵が作られた - その弱い鍵を持つ中間CAが、ルートCA「emSign ECC Root CA - G3」の配下で、信頼される証明書として作られてしまった - 2026年10月17日、研究者がブラウザベンダーとeMudhraに報告した。Mozillaは実際に公開鍵から秘密鍵を取り出せることを確認した - 対象はTLS用の中間CAが6つ、コード署名用の中間CAが2つ ChromeとFirefoxはその日のうちに中間CAをブロックしました。その後、ルートCA「emSign ECC Root CA - G3」そのものも信頼の一覧から外されることになりました。 リスク①:偽の証明書を信じてしまう(クライアント側) 鍵を手に入れた攻撃者は、たとえば github.com や api.example.com の証明書を作れます。クライアントがまだこの中間CAを信頼していれば、偽の証明書は正当なものとして通ります。 すると、通信経路の途中にいる攻撃者(公衆Wi-Fi、乗っ取られたルーター、DNSの書き換えなど)が、本物のサーバーになりすませます。そして通信を盗み見たり書き換えたりできます。いわゆる中間者攻撃(MITM)です。 イメージ図 !スクリーンショット 2026-10-25 18.41.55.png ポイントは④です。押されているのは本物の印鑑なので、クライアントは証明書をたどってトラストストアと照合しても、偽物だと気づけません。 逆に、クライアントのトラストストアが更新されていれば、同じ攻撃をされても④で止まります。 !スクリーンショット 2026-10-25 18.42.40.png 今回のパッチ当てやバージョンアップは、自分たちのクライアントを、この「アップデート後」の状態にするための作業です。 コード署名用の中間CAが使われると、マルウェアに正規の署名を付けて正しいソフトウェアに見せかけることもできます。 ブラウザは比較的安全、ブラウザ以外が危ない Chromeは、公開された証明書に CT(Certificate Transparency) を求めます。CTは、発行された証明書をすべて公開ログに記録する仕組みです。ログに載っていない証明書は信頼されません。Googleによると、ブロックするまでに、この中間CAにつながる証明書はCTログに記録されていませんでした。そのため、CTを強制するクライアントに対して偽の証明書が使われることはなかったとしています。 一方で、curl、Pythonの requests、Goの net/http、Javaの HttpClient などは、ふつうCTをチェックしません。ブラウザのような即時ブロックの仕組み(ChromeのCRLSetなど)もありません。 つまり、残るリスクはサーバー間通信、バッチ、CLI、社内ツールのような「ブラウザ以外のクライアント」に集中しています。 外部APIを呼ぶバックエンドや、決済、認証の連携などがそれに当たります。 Cloudflareのブログでも、次のように書かれています。 > A successful browser test does not prove that a background service is protected ブラウザで問題なく見えても、裏で動いているサービスが守られているとは限りません。 リスク②:自分の証明書が使えなくなる(サーバー側) 今回はルートCA「emSign ECC Root CA - G3」ごと信頼されなくなります。そのため、鍵が漏れていない中間CAから発行された正しい証明書も、このルートにつながっていれば使えなくなります。 Googleの集計では、対象の証明書は約3万件です。ほとんどは米国の教育研究機関向けのInCommonの証明書でした。ChromeからのルートCA削除は、2026年10月27日(米国太平洋時間) に、Chromeのルート証明書一覧を使う端末へ配信される予定です。 自社のサイトや、自社が呼んでいる外部APIがこのルートの証明書を使っていると、その日以降接続エラーになります。セキュリティの問題ではありませんが、障害(可用性の問題)になります。 なぜ「全部アップデート」が必要なのか 自分としてはここがよく分かっていませんでした。 答えは、「どのCAを信頼するか」の一覧(トラストストア)が、1か所ではなくいろいろな場所にあるからです。 | 持っている場所 | 例 | 今回の対応 | |---|---|---| | OS | Ubuntu / Debian の ca-certificates、RHEL | パッケージ更新でルートを削除 | | ブラウザ | Chrome Root Store、Firefox(NSS) | CRLSet / OneCRLで中間CAをブロック、ルートを削除 | | Go | crypto/x509 | 対象の中間CAを含むチェーンを拒否 | | Node.js | 本体に内蔵したCA一覧 | セキュリティリリースで更新 | | Java | JDKの cacerts | Oracleが中間CAを不信頼にする更新を提供 | | Python | certifi(requests などが使う) | パッケージ更新 | | PHP | Composer の ca-bundle | 中間CAを不信頼に | | Rust | webpki-roots | ルートを削除 | | Electronアプリ | ChromiumとNode.jsの両方を内蔵 | 修正版への更新が必要 | たとえば次のような状況が起こります。 - OSの ca-certificates を更新しても、Pythonの requests は certifi の一覧を見ているので守られない - certifi を更新しても、pipは自分専用のcertifiを内蔵しているので、pip自体の更新も必要 - Node.jsは、デフォルトでは本体に内蔵したCA一覧を使う。そのためOSを更新してもNode.jsの更新が必要 - コンテナは、ベースイメージを作り直してデプロイし直さないと古いトラストストアのまま - 長く動いているプロセスは、起動時に読み込んだトラストストアを使い続けることがある。更新後に再起動が必要 Cloudflareのブログにある次の一文が、この状況をよく表しています。 > Updating the SDK alone may not change the underlying policy. SDKを上げても、実際に証明書を検証しているのはその下のHTTPライブラリやランタイム、OSかもしれません。だから「依存関係の下のほうまで確認して、全部上げる」という対応になります。 自分の環境を確認する 確認は、各ベンダーのアドバイザリにある修正済みのバージョン以上になっているかで判断してください。 まずはバージョンを確認する | 対象 | 修正済みのバージョン | 確認先 | |---|---|---| | Ubuntu の ca-certificates | 22.04:20260816ubuntu0.22.04.1<br>24.04:20260816ubuntu0.24.04.1<br>26.04:20260816ubuntu0.26.04.1 | USN-8944-1 | | Red Hat(RHEL) | アドバイザリを参照 | RHSB-2026-012 | | Node.js | v22.23.4 / v24.22.1 / v26.12.1 | October 21, 2026 Security Releases | | Python の certifi | 2026.10.19 以上 | Python Discourse | | pip | 26.2.2 以上 | 同上 | | uv | 0.13.4 以上 | 同上、uvのアドバイザリ | | Go | 1.26.10 / 1.27.3 | Release History、golang/go#82345 | | Java(Oracle) | アドバイザリを参照 | CVE-2026-91403 | | Firefox | アドバイザリを参照 | MFSA 2026-111 | | Electron | アドバイザリを参照 | GHSA-jr5w-w6x2-84p9 | | PHP(Composer の ca-bundle) | リリースノートを参照 | composer/ca-bundle | | Rust(webpki-roots) | リリースノートを参照 | rustls/webpki-roots | サーバー側:自分の証明書が対象か # ここを自分のサイトや、呼んでいる外部APIのホスト名に変える HOST=api.example.com # 証明書のつながりを表示する openssl s_client -connect "$HOST:443" -servername "$HOST" -showcerts </dev/null 2>/dev/null \ | grep -E "^ *[0-9]+ s:|^ +i:" example.com で試すと、次のように表示されます。 0 s:/CN=example.com i:/C=US/O=SSL Corporation/CN=Cloudflare TLS Issuing ECC CA 3 1 s:/C=US/O=SSL Corporation/CN=Cloudflare TLS Issuing ECC CA 3 i:/C=US/O=SSL Corporation/CN=SSL.com TLS Transit ECC CA R2 ... - s:(subject)は誰の証明書か - i:(issuer)は誰が印鑑を押したか 前提知識のたとえで言うと、「証明書 → 支店 → 本社」のつながりがそのまま表示されています。emSignが関係していれば、どこかの行に「emSign ECC Root CA - G3」が出てきます。別の本社からもお墨付きをもらっている(クロス署名)場合もあるので、いちばん下の行だけでなく全体を見てください。 | 結果 | 意味 | |---|---| | つながりが表示され、「emSign ECC Root CA - G3」がどこにもない | 対象外 | | どこかに「emSign ECC Root CA - G3」がある | 対象。証明書の差し替えが必要 | | 何も表示されない | 接続できていない。ホスト名、ポート、ネットワークを確認する | 443以外のポートで動いているサービスは、$HOST:443 のポート番号を変えてください。自社サイトだけでなく、自社が呼んでいる外部APIのドメインも確認しておくと安心です。 動作確認用のページ we-have-a-problem.com には、問題の中間CAにつながる証明書を使ったテスト用のサーバーが用意されています。ページ自体はふつうの証明書なので、普通に開けます。ページを開くと、ブラウザがテスト用のサーバーに自動でつなぎにいきます。 - ✅:つながらなかった(正しくはじかれた)。ただし、ネットワークの問題でつながらなかった場合も✅になります - つながった:まだ問題の中間CAを信じてしまっている このページでわかるのは、開いたブラウザのことだけです。サーバーやバッチは、ページに載っている curl のコマンドで確認してください。 ブラウザ(Chrome)での結果 手元のMac(macOS 27.0.1)のChromeでページを開くと、14本すべてが「Did not connect」になりました(2026年10月25日時点)。 !スクリーンショット 2026-10-25 19.27.54.png 最後の行の「Your browser trusted 0 of 14 compromised certificate chains.」は、問題の中間CAにつながる証明書を1本も信じなかった、という意味です。Googleの発表どおり、Chromeは守られています。 curlコマンドの実行(良くない例) $ curl https://dv-g3b-emudhra.we-have-a-problem.com/ Your client successfully connected to the site. That's bad! $ curl https://dv-g3b-aaa-emudhra.we-have-a-problem.com/ Your client successfully connected to the site. That's bad! 同じMacのターミナルで、curl を実行した結果です。Chromeでははじかれたサーバーに、curl ではつながってしまいました。 同じMacから同じサーバーにつながっているので、Chromeの「Did not connect」はネットワークの問題ではなく、正しくはじいた結果だということもわかります。 報道や有志のまとめによると、Appleは10月19日に、OSのアップデートではなく「取り消した証明書のリスト」を配る仕組みで、問題の中間CAをブロックしています。そのため、SafariやAppleの標準の仕組みで通信するアプリは守られています(一部の環境ではまだつながるという報告もあります)。 ところが、curl、git、python3 などのターミナル用のツールは、/etc/ssl/cert.pem という別の証明書の一覧ファイルを使っていて、このリストを見ません。このファイルは更新されておらず、手元のMacでもemSignのルートが残っていました。同じMacの中でも、ブラウザは守られているのに、ターミナルのツールは守られていない。まさに「ブラウザは比較的安全、ブラウザ以外が危ない」の状態です。 この時点では、最新のmacOSにしても、ターミナルのツールが使う一覧は更新されていません。公衆Wi-Fiなど信頼できないネットワークで、curl やスクリプトを使って大事な通信をするのは避けたほうが安心かと思います。 まとめ - 中間CAの秘密鍵が漏れると、どのドメインの証明書でも偽造できる - リスクは2つ。偽の証明書を信じるリスク(クライアント側) と、自分の証明書が使えなくなるリスク(サーバー側) - ブラウザはCTと即時ブロックの仕組みで比較的早く守られた。残るリスクはブラウザ以外のクライアント - トラストストアはOS、ランタイム、ライブラリ、アプリがそれぞれ持っている。だから全部のアップデートと再起動・再デプロイが必要 最初は「言われたから対応している」という状態でしたが、記事にまとめてみて、なぜこれだけ対応範囲が広範なのか、自分の中で整理できた気がします。 セキュリティの対応はスピードが大事なので、頭の整理が後回しになってしまうところもあるかもしれませんが、その都度時間を取ってキャッチアップしたいですね、、 参考 - eMudhraの中間CA証明書の秘密鍵の危殆化についてまとめてみた - piyolog - Protecting Chrome and Android Users from Compromised eMudhra Intermediate CA Certificates - Google - Protecting Firefox users following the compromise of eMudhra intermediate certificates - Mozilla - 8 eMudhra certificates are compromised. Here's what you need to know - Cloudflare - Bug 2083449 - eMudhra: Private key compromise of Intermediate Certificates - Mozilla Bugzilla - crypto/x509: mitigation for security concerns with a specific Certificate Authority - Go - October 21, 2026 Security Releases - Node.js

  3. Done updating PHP? Composer 2.11 RC1 is available with a cooldown policy, terminal progress reporting via OSC 7501, and a whole lot of fixes including security checks against the compromised eMudhra certificates. Try it out now! github.com/composer/composer/releases/tag/2.11.0-… #composerphp

    8 likes · 520 views
  4. eMudhra の CA 鍵漏洩と PHP2Shell、同じ週に来た2つの緊急対応を一次ソースで整理する ! この記事は、2026/10/22 14:00(日本時間)までに公開された一次ソースをもとにまとめている。どちらの件も状況が変わり続けているので、作業の前にリンク先で最新の情報を確認してほしい。 10/21 の夜、高市首相が X にこんな投稿をしていた。 皆様に、今夜に対応して頂きたい大至急のお願いです。 多くのウェブサイトで使用されているPHPに関し、PHPのセキュリティチームが、重大な2件の脆弱性に関する注意喚起を行っています。 投稿は、23:00 に公開される修正パッチをすぐ適用できるよう準備してほしい、難しければウェブサイトを一時的に止めることも有効策の一つだ、と続く。首相が個別のソフトウェアの脆弱性について直接呼びかけるのは珍しく、ITmedia はエンジニアの反応まで記事にしていた。日経によると、首相自身のホームページもその夜から止めていたらしい。 この PHP の脆弱性(PHP2Shell)と同じ週に、もうひとつ、ブラウザ以外の TLS クライアントに広く関わる認証局の鍵の問題も明らかになっている。この記事では、2つの件をそれぞれ一次ソースで整理していく。 TL;DR この1週間で、性質のまったく違う緊急対応が2つ重なった。2つは別々の事件で、互いに関係はない。 eMudhra の中間 CA 鍵漏洩では、インドの認証局 eMudhra の中間 CA 証明書8枚について、秘密鍵を公開情報から誰でも計算できる状態だったことが分かった。この鍵があれば、任意のドメインの偽サーバー証明書を作れる。主要なブラウザは CT(後述)のおかげで偽証明書を受け付けないので、危ないのは Go / Java / Node.js / Python / Rust などで書いたプログラムや curl のような、ブラウザ以外のクライアントのほうだ。対策は言語ごとに違い、OS の更新だけでは済まないものも多い。 PHP2Shell(CVE-2026-109618 / CVE-2026-109619)は、認証なしでリモートからコードを実行できてしまう PHP 本体の脆弱性だ。修正版の PHP 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 は、10/21 の 23:00 ごろに公開された。mod_php ではアプリのコードが1行も動く前に攻撃が成立し、PHP-FPM などほかの構成も対象になる。設定で完全に塞ぐ方法はなく、更新するしかない。 PHP を使っているなら両方に関係がある。PHP2Shell の更新に加えて、PHP から外に出る HTTPS 通信(Composer や外部 API の呼び出し)が eMudhra の件の影響を受けないかも確認しておきたい。 第1部 eMudhra の中間 CA 鍵漏洩 ! エンジニアでない人が、まず確認しておきたいこと スマートフォンと PC の OS を最新にする。Apple などはまだ対応しきれていない可能性があるので、この先しばらくはアップデートが来たらすぐ入れる ブラウザと、普段使っているアプリ(Slack や VS Code など)を最新にする この件で危ないのは、主にサーバーや開発ツールだ。会社でサービスを運営しているなら、エンジニアに「この記事のまとめにある eMudhra の確認項目を済ませたか」を聞いてもらえばいい。 何が起きたのか この件の情報は、Mozilla の Dennis Jackson さんが公開した emudhra.we-have-a-problem.com というまとめページに集まっている。冒頭にはこう書かれている。 The private keys of eight eMudhra intermediate CA certificates have been compromised. They chain to roots trusted by the Mozilla, Microsoft, Apple and Chrome root programs and by many downstream trust stores. 8枚の中間 CA 証明書の秘密鍵が漏れていて、しかもそれらは主要なルートプログラムすべてが信頼するルートにつながっている、という内容だ。この問題を見つけて報告した Wayne さんは、各中間 CA の秘密鍵で We have a problem here - Wayne というメッセージに署名し、鍵を持っていることを証明していて、まとめページのドメイン名もこの署名メッセージから来ている。 Mozilla の Bugzilla #2083449 と各社の発表をもとに、時系列を日本時間で並べた。 日時(日本時間) 出来事 2025/4/30 eMudhra の鍵生成セレモニーで問題の鍵が作られる 2026/10/18 03:05 Wayne さんが Apple / Chrome / Microsoft / Mozilla / eMudhra に報告 10/18 04:45 Chrome が CRLSet(Chrome が配信する失効リスト)で TLS 用の中間 CA 6本をブロック 10/18 07:59 Firefox が OneCRL(Firefox が配信する失効リスト)でブロック(ブラウザの更新は不要) 10/18 18:24〜 eMudhra が8本を失効 10/19〜20 Sectigo がクロス署名版を失効。Apple がブロック 10/20〜21 Microsoft がブロック。Mozilla と Chrome がルート emSign ECC Root CA - G3 の緊急削除を決定。certifi・Go・Node.js などが 10/19〜21 にかけて修正版を公開 10/28(予定) Chrome Root Store v43 で emSign ECC Root CA - G3 を削除 対象の中間 CA は EM DV/OV/EV TLS CA - G3B、G3C の TLS 用6枚と、コード署名用の EM OV CS CA - G3B/G3C の2枚。それぞれに、eMudhra のルートから発行された版と、別の認証局 Sectigo のルート AAA Certificate Services(旧 Comodo AAA)が同じ鍵に署名した版(クロス署名)があるので、鍵は8本でも証明書としては16枚になる。フィンガープリントの一覧は impacted-intermediates.json にまとまっている。 鍵はどれくらい弱かったのか これが今回いちばん衝撃的なところだと思う。Mozilla の担当者が Bugzilla に書いた分析を引用する。 P384 private keys are randomly selected integers between 1 and the group order. The 8 impacted keys all used integers less than 256. That is, the private keys are effectively all-zeroes apart from the last byte. P-384 の秘密鍵は本来なら2の384乗に近い範囲からランダムに選ばれるが、今回の8本はどれも 256未満 で、最後の1バイト以外が全部ゼロだった。これなら1から255までを順に試せば必ず当たり、復元には1秒もかからない。同じコメントには、AI エージェントに「CTF をやっているので、この証明書の秘密鍵を復元して」と頼んだら一発で復元できた、という報告まである。 As this incident enables even technically unsophisticated individuals to easily recover the private keys for these intermediates, the impact of this incident could not be higher. なぜこんな鍵ができたのかについて、eMudhra は Bugzilla でこう説明している。 an approved deviation to our usual KGC to test a wrap/unwrap was introduced as these keys were meant for export for this instance c) a flaw in the code resulted in the second pair of keys being created onboard which were weaker these second pair of weaker keys were used by mistake to create the csr (because the key labels were similar) 鍵をエクスポートするための wrap/unwrap(鍵を暗号化して取り出す処理)をテストしたときに、コードの不具合で HSM の中に弱い鍵がもう1組作られ、ラベルが似ていたせいで間違ってそちらを CSR に使ってしまった、と説明している。eMudhra の公式声明によると、この状態は約18か月、2回の独立監査でも見つからなかったらしい。とはいえ同じ声明には「正確な根本原因はまだ確定していない」とも書かれていて、Chrome Root Program は eMudhra に12項目の質問を送っている。 何が危ないのか 秘密鍵を持っていれば、その中間 CA の名前で、任意のドメインのサーバー証明書を発行できる。たとえば api.github.com や pypi.org の偽証明書を作り、公衆 Wi-Fi や社内のプロキシ、DNS の乗っ取りなどで通信経路の途中に入り、中身を読んだり書き換えたりする中間者攻撃が成立してしまう。残りの2本はコード署名用で、Windows がこれを信頼していたため、偽の署名を付けたプログラムを作れてしまう可能性もあった。 ただし、ブラウザでは偽証明書を使った攻撃は成立しなかったと、まとめページは判断している。Chrome / Safari / Firefox / Edge は Certificate Transparency(CT)という公開ログに記録されていない証明書を受け付けず、問題の中間 CA から発行された証明書は CT ログに1枚も記録されていないからだ。 There are no entries in the certificate transparency logs for these intermediates in that period, indicating that CT-enforcing clients like Firefox, Chrome, Edge and Safari could not have been attacked. However, many clients outside of the browser ecosystem do not enforce Certificate Transparency. これに対して、curl や OpenSSL、各言語の HTTP クライアント、IoT 機器などは CT を確認しない。失効情報(CRL や OCSP)も、デフォルトでは確認しないものが多い。こうしたクライアントは、攻撃者が CT に記録せずに作った偽証明書を、そのまま受け入れてしまう。しかも鍵が弱かったのは2025年4月の生成時点からなので、その間に悪用されたかどうかは誰にも分からない。 まとめページは、問題の中間 CA の証明書をわざと使ったテスト用ホストを立てていて、そこへの接続に成功したクライアントの統計も公開している。10/22 13:30(日本時間)の時点で、直近24時間の接続成功は約16.9万回あり、UA(クライアントが名乗る名前)別に見ると、iOS の WebView や Safari が上位に並び、そのあとに macOS 標準の curl のバージョンである curl/8.7.1 が続いている。 iOS が上位にいるのは意外かもしれない。まとめページは Apple も 10/19 にブロックしたとしているが、統計ではテスト用ホストのうち eMudhra のルート経由のチェーンに iOS からの接続成功が集中している。iOS の信頼ストアの更新は、まだ完全ではないのかもしれない。CT に記録されていない偽証明書なら Safari は受け付けないが、iOS のアップデートが来たら早めに入れておきたい。 macOS 26.6.2 の標準の /usr/bin/curl でテスト用ホストに接続すると普通につながり、Your client successfully connected to the site. That's bad! と返ってきてしまった。macOS の標準の curl、git、python3、perl、ruby が参照する /etc/ssl/cert.pem が、この時点ではまだ更新されていないことが原因になっている。 巻き添えで正規の証明書も止まる eMudhra から正規に証明書を買っていたサイトにも影響が出る。Mozilla と Chrome はルート emSign ECC Root CA - G3 ごと信頼を外すと決めたので、その配下の正規の証明書も信頼されなくなる。 After discussion with maintainers downstream of Mozilla's Root Store, we have decided that the circumstances warrant the emergency removal of trust in emSign ECC Root CA - G3. This will protect clients which do not use revocation information or lack a mechanism to withdraw trust in specific intermediates. Chrome の集計では、影響を受ける有効な証明書は約3万枚で、その99.9%は、米国の大学向けの証明書サービス InCommon の下位 CA から発行されたものだった。eMudhra は G1(RSA)系のルートへの移行を進めていて、Google はサイト運営者に別の認証局の証明書へすぐ切り替えるよう求めている。eMudhra の証明書を使っているサイトの運営者は、Chrome Root Store からルートが外れる 10/28 までに証明書を入れ替える必要がある。 修正の方式は2通りあるが、利用者が選ぶ必要はない ここからは、言語やツールごとの対応を見ていく。先に結論を書いておくと、ここで紹介する2つの方式は各プロジェクトが修正版の中で採った方式の違いで、利用者がどちらかを選ぶ必要はない。使っている言語やライブラリを修正版にし、Go や Rust のようにビルドして作るものは作り直せば、そのツールの方式で対策が入る。とはいえ、方式によって「OS の更新だけで足りるか」が変わってくるので、仕組みを知っておくと更新の漏れに気づきやすいと思う。 1つ目は、侵害された8本の公開鍵(SPKI)を拒否するリストを、検証の処理に組み込む方式だ。Go、Node.js、rustls-webpki(Rust)、Deno、Electron がこの方式をとり、Composer 本体も同じ仕組みを開発版に入れている。証明書ではなく公開鍵で判定するので、Sectigo のクロス署名版もまとめて拒否でき、OS の証明書ストアを使う設定でも有効になる。 2つ目は、同梱している CA バンドルからルート証明書を削除する方式で、Python の certifi、Rust の webpki-roots、Python のパッケージマネージャ uv、Elixir の castore、Perl の Mozilla::CA、composer/ca-bundle、Bun、Homebrew がこちらにあたる(どれも Mozilla のストアをもとにした CA バンドルを同梱している)。この方式は、そのバンドルを実際に使っている場合にしか意味がない。 利用者の目線で整理すると、1つ目の方式は、ツールやライブラリを修正版にすれば OS の設定に関係なく対策が入る。2つ目の方式は使い方で変わり、同梱のバンドルを使っていればツールの更新、OS のストアだけを使う設定なら OS の更新で直り、pip や Node.js の --use-system-ca のように両方を併用するツールなら両方の更新が要る。 つまり、利用者がやることは次の3つで足りると思う。 使っている言語・ライブラリを修正版にし、Go や Rust などビルドするものは作り直す OS の証明書を更新し、コンテナはイメージを作り直す 更新したら、長時間動いているプロセスを再起動する Java はどちらの方式とも違い、blocked.certs というファイルで証明書を1枚ずつブロックしていて、OS のパッケージで入れた JDK なら OS の更新で足り、単体で配布されている JDK は本体の更新が必要になる。macOS の /etc/ssl/cert.pem や RHEL のように修正がまだ出ていない環境は、後述の回避策を使う。他社が配布している Go 製の CLI や Electron アプリは利用者の側では直せないので、配布元の更新を待つしかなくなってしまう。 certifi のメンテナは、2つ目の方式しかとれない理由をこう書いている。 there's no facility for revoking an intermediate only もうひとつ気をつけたいのが、Node.js の --use-system-ca や pip(24.2 以降)のように、同梱バンドルに OS の証明書ストアを追加して使うツールだ。OS を更新してルートが消えても、古い同梱バンドルにルートが残っていれば、信頼されたままになってしまう。Node.js のドキュメントにも次のように書かれている。 Node.js currently does not support distrust/revocation of certificates from another source based on system settings. 言語・ランタイム別の対応状況 対象 修正版 仕組み やること Go 1.27.3 / 1.26.10(10/20) crypto/x509 に侵害された中間 CA の拒否リスト(CVE-2026-111943) 修正版の Go で再ビルドして再デプロイ Node.js 22.23.4 / 24.22.1 / 26.12.1(10/21) NSS 3.131.1 のルート更新と、SPKI 拒否リストの両方 Node 本体を更新。コンテナはイメージを作り直す Java (OpenJDK) advisory は 27.0.1 / 25.0.5 / 21.0.13 / 17.0.21 / 11.0.33 / 8u512 以前を影響ありとしている(CVE-2026-91403) blocked.certs で証明書を個別にブロック 単体配布の JDK は更新。OS パッケージの JDK は OS の証明書更新で足りる、と advisory にある Python certifi 2026.10.18 / 2026.10.19 10.18 で emSign のルートをまとめて削除し、10.19 で影響のない3本を戻した。いま外れているのは emSign ECC Root CA - G3 pip install -U certifi。requests は certifi しか見ないので必須 pip 26.2.2(10/20) 同梱の certifi を更新 python -m pip install -U pip uv 0.13.4(10/20) 同梱バンドルからルートを削除 uv self update rustls-webpki 0.103.16(10/20) SPKI 拒否リスト cargo update -p rustls-webpki して再ビルド webpki-roots 1.0.10(10/19) ルートを削除 cargo update して再ビルド Deno 2.9.8(10/21) rustls-webpki と webpki-roots の修正を取り込み deno upgrade。deno compile したバイナリは作り直す Electron 44.9.1 / 43.8.1 / 42.11.16(10/20) SPKI 拒否リスト アプリ開発者が更新して再配布 Bun 修正は main にマージ済みで、リリースは未公開 ルートを削除 次のリリースを待つ Elixir castore 1.0.22(10/20) ルートを削除 mix deps.update castore Perl Mozilla::CA 20261020 ルートを除外 cpanm Mozilla::CA Homebrew ca-certificates 2026-10-20 ルートを除外 brew upgrade ca-certificates。Homebrew の curl / OpenSSL / Python が参照する Ruby / .NET / CPython の ssl 本体の修正なし 多くの環境で OS のストアを使う OS の証明書を更新する 表の中では Electron が見落としやすい。Chrome は CRLSet という仕組みでブロックリストを配信しているが、Electron はこれを受け取らないので、Chromium を内蔵していても Chrome と同じ保護は受けられない。Electron の PR にもそのまま書かれている。 add entries to the compiled-in SPKI blocklist that Chrome ships via CRLSet, which Electron does not consume. Java のバージョン番号は、まとめページの表(8u511 など)と OpenJDK の advisory(8u512 以前が影響)で食い違っていて、記事の時点では確定できなかった。Oracle JDK の情報も確認できていないので、Java を使っている人は配布元で直接確認してほしい。 OS・ディストリビューション別の対応状況 対象 修正版 内容 Ubuntu USN-8944-1(22.04 以降は 20260816ubuntu0.<リリース番号>.1)、USN-8944-2(ESM) emSign ECC Root CA - G3 を削除。ESM 版は Comodo AAA も削除 Debian DSA-6572-1(trixie 20250419+deb13u1)、DLA-4845-1(bookworm 20250419~deb12u2) G3 と Comodo AAA を無効化 Fedora ca-certificates-2026.2.92_v9.0.319 G3 と AAA を削除 RHEL 6〜10 記事の時点で RHSA は未公開 当面は2つのルートを手動でブロックするよう案内している Alpine ca-certificates 20261020-r0 上流の更新に追従してルートを削除 Arch ca-certificates-mozilla 3.131.1-1 同上 FreeBSD SA-26:73 G3 を untrusted に curl の cacert.pem 2026-10-20 版 Mozilla のストアに追従 macOS /etc/ssl/cert.pem は未更新 後述の回避策を参照 Windows Microsoft の自動更新(Disallowed CTL)で配信済み ルートはそのままで、中間 CA の証明書をブロック(まとめページによると16枚) Ubuntu の通常版が Comodo AAA を無効化していないのは、Mozilla のストアにこのルートがすでに入っておらず、最新の ca-certificates にも含まれていないためだ。古いバンドルを使い続けている ESM 版や Debian、Fedora は、念のため AAA も無効化している。 RHEL と Amazon Linux の ca-certificates の更新と、Android の公式発表は、記事の時点では見当たらない。 どの OS でも、ca-certificates を更新したあとは、長時間動いているプロセス(Java や Node.js のサーバーなど)を再起動しておきたい。起動時に読み込んだ証明書を持ち続けるプログラムがあるからだ。 コンテナは作り直さないと直らない コンテナイメージには、ビルドした時点の ca-certificates が入っている。ホストの OS を更新してもコンテナの中は古いままなので、イメージを作り直す必要がある。 Docker の公式イメージは、Debian を 10/20 に、Alpine を 10/21 に更新している。Debian のベースイメージには ca-certificates が入っていないので一見関係なさそうだが、派生イメージの再ビルドを促すために、あえて更新したらしい。 The Debian images don't contain ca-certificates, but many downstream images do… updating Debian is the simplest way to trigger downstream rebuilds. node:24 や python:3.14 のような浮動タグを使っている場合も、docker pull し直してからビルドしないと古いレイヤーが使われてしまうので注意したい。 PHP の場合 PHP 本体(php-src)にはこの件の修正は入っていないが、openssl 拡張も curl 拡張も、OS の証明書ストアか、openssl.cafile / curl.cainfo で指定したファイルを見る作りなので、OS の ca-certificates を更新すれば対策になる。 では、Composer まわりはどうか。composer/ca-bundle は 1.6.0 / 1.4.16 で同梱の cacert.pem から emSign ECC Root CA - G3 を抜いた。ただ、CaBundle::getSystemCaRootBundlePath() は SSL_CERT_FILE、openssl.cafile、OS の既知のパスの順に探し、同梱ファイルは最後の手段としてしか使わないので、OS のストアが見つかる普通の環境では、この削除の影響はほぼないと思う。PR の本文にも、次のように書かれている。 Removing the root from our bundle does not help users whose system CA store is used, so clients like Composer can use this to reject such connections. そのため ca-bundle には、SPKI でチェーンを判定する CaBundle::findDistrustedCertificate() という API が追加され、これを使って Composer 本体が接続を拒否する PR #13146 も 10/21 に main にマージされたものの、記事の時点ではまだリリースされていない。それまでは、Composer を実行するマシンの OS の証明書を更新しておくのが確実だと思う。 ちなみに、Guzzle は composer/ca-bundle に依存しておらず、デフォルトでは OS のストアを使う。WordPress が使っている HTTP ライブラリの WordPress/Requests は、2.0.21 で対応済みだ。 自分の環境が影響を受けるか確認する いちばん手軽なのは、まとめページが用意しているテスト用ホストに、普段使っているクライアントで接続してみることだ。 curl dv-g3b-emudhra.we-have-a-problem.com curl dv-g3b-aaa-emudhra.we-have-a-problem.com 証明書エラー(curl: (60) など)になれば安全で、Your client successfully connected to the site. That's bad! が返ってきたら、まだ問題の中間 CA を信頼している。上が eMudhra のルート経由、下が Sectigo のクロス署名経由のチェーンなので、両方試すのがいいと思う。 curl だけでなく、アプリが実際に使っている言語で同じ URL にアクセスしてみるほうが確実だ。 Python (requests) python -c "import requests; print(requests.get('dv-g3b-emudhra.we-have-a-problem.com').text)" Node.js node -e "fetch('dv-g3b-emudhra.we-have-a-problem.com').then(r=>r.text()).then(console.log)" PHP php -r "echo file_get_contents('dv-g3b-emudhra.we-have-a-problem.com');" どれも、エラーで落ちれば安全だ。 証明書バンドルのファイルに、問題のルートが残っているかを直接見ることもできる。 B=/etc/ssl/certs/ca-certificates.crt # RHEL 系は /etc/pki/tls/certs/ca-bundle.crt、macOS は /etc/ssl/cert.pem awk '/-----BEGIN CERTIFICATE-----/{c=""} {c=c $0 "\n"} /-----END CERTIFICATE-----/{cmd="openssl x509 -noout -subject -fingerprint -sha256 | paste - -"; printf "%s", c | cmd; close(cmd)}' "$B" \ | grep -E "emSign ECC Root CA - G3|AAA Certificate Services" || echo "not found (OK)" not found (OK) と出れば、そのバンドルには残っていない。 OS の更新が来ていないときの回避策 まとめページには、更新が出ていない環境向けの回避策が載っている。とはいえ、ページ自身が上級者向けとしていて、Linux 向けの手順には一般のユーザーにはおすすめしないとも書かれているので、自分で戻せる人だけが使ってほしい。以下はまとめページのコマンドをそのまま引用している。 macOS の /etc/ssl/cert.pem から2つのルートを外す場合(バックアップを取ってから書き換える)。 sudo cp -p /etc/ssl/cert.pem /etc/ssl/cert.pem.bak && sudo awk '/^(###|===) /{skip=0} /^=== .*\/CN=(AAA Certificate Services|emSign ECC Root CA - G3)$/{skip=1} !skip' /etc/ssl/cert.pem.bak | sudo tee /etc/ssl/cert.pem > /dev/null Debian / Ubuntu の場合。 sed -i \ -e 's|^mozilla/emSign_ECC_Root_CA_-_G3.crt|!&|' \ -e 's|^mozilla/Comodo_AAA_Services_root.crt|!&|' \ /etc/ca-certificates.conf && update-ca-certificates Fedora / RHEL / Rocky / Alma / Amazon Linux 2023 の場合。 d=/etc/pki/ca-trust/source/blocklist; [ -d $d ] || d=/etc/pki/ca-trust/source/blacklist trust extract --overwrite --format=pem-bundle \ --filter='pkcs11:object=Comodo%20AAA%20Services%20root;type=cert' \ $d/Comodo_AAA_Services_root.pem && trust extract --overwrite --format=pem-bundle \ --filter='pkcs11:object=emSign%20ECC%20Root%20CA%20-%20G3;type=cert' \ $d/emSign_ECC_Root_CA_-_G3.pem && update-ca-trust Comodo AAA まで外すと、正規の Sectigo の証明書が壊れないか気になるところだと思う。Chrome はこのルートを2025年4月に削除していて、Mozilla のストアにもすでに入っていない。AAA のクロス署名つきチェーンを返す Sectigo のサイトに、AAA を抜いたバンドルで接続してみると、新しい OpenSSL / LibreSSL は、別の正規のルートまでチェーンを構築し直して問題なく接続できた。かなり古い OpenSSL のようにチェーンを構築し直さないクライアントでは、失敗することもあると思う。 Windows は自動更新でブロックが配信されているので通常は何もしなくてよく、自動更新を受け取らない端末向けには、まとめページに PowerShell スクリプトが用意されている。 第2部 PHP2Shell ! エンジニアでない人が、まず確認しておきたいこと レンタルサーバー(さくら、ロリポップ!、エックスサーバーなど)でサイトを運営しているなら、管理画面で PHP のバージョンを確認する。8.1 以前なら、バックアップを取ってから 8.2 以上に切り替える。8.2 以上なら、事業者のお知らせで修正済みとなっていれば作業は終わり VPS や自社のサーバーで動かしているなら、エンジニアに「PHP を修正版に更新して、PHP-FPM や Apache を再起動したか」を確認してもらう なお、WordPress 本体を最新にしても、この脆弱性は直らない。直す必要があるのはサーバー側の PHP だ。 何が起きたのか こちらは PHP 本体の脆弱性で、CVE-2026-109618 と CVE-2026-109619 の2件をまとめて PHP2Shell と呼んでいる。どちらも CVSS v4.0 で 9.2。PHP の公式発表では、影響する範囲をこう書いている。 Who is at risk: all PHP installations serving web requests, including PHP-FPM, Apache with mod_php, php-cgi, FrankenPHP and LiteSpeed. We consider the risk highest for mod_php, with a demonstrated exploit where an unauthenticated request can trigger the attack before any application code runs. Web リクエストを処理しているすべての PHP が対象で、とくに mod_php では、認証なしのリクエストで、アプリのコードが動く前に攻撃が成立することが検証環境で実証されている。cron やコマンドラインだけで PHP を使っている場合については、公式は個別に触れていない。 経緯を PHP Foundation のブログと各社の公開記事をもとに並べた。 日時 (JST) 出来事 2024年 外部監査(Quarkslab)の指摘を修正していた PHP のコア開発者が、CVE-2026-109618 の原因になる OOM の問題の最初の兆候に気づく 2026年8月 Calif と OpenAI が 8/11 に、Wiz が 8/24 に、それぞれ独立に PHP へ報告 10/21 00:00 頃 CVE 番号が SNS やフォーラムで出回り始める(誤った CVSS 10.0 つき) 10/21 04:30 PHP が事前告知。当初の予定(10/22)を1日前倒しし、10/21 23:00 JST にリリースすると発表 10/21 05:00 頃 Calif が PoC の動画を誤って公開した(PHP Foundation による) 10/21 16:41 Chainguard が修正入りのコンテナイメージを先行して公開。PHP Foundation は、情報公開の取り決め(エンバーゴ)を破ったと批判している 10/21 22:34 GitHub Security Advisory 公開 10/21 23:00 ごろ 修正版を公開(予告は 23:00 だったが、実際の公開は数分〜十数分ほど早かった) 情報が予定より早く漏れたため、リリースを1日前倒しした。PHP Foundation は、ディストリビューションのパッケージングがまだ終わっていない中での判断だったと書いている。 Moving the release forward by one day was the best compromise between acting quickly, giving people time to prepare, and making sure everyone had a simple update path when the vulnerabilities were disclosed. 2つの脆弱性の中身 公式の GHSA によると、2件の内容はこうなっている。 CVE-2026-109618(GHSA-w8hw-w9fx-j79w「RCE via OOM corruption」)。PHP はメモリ不足(OOM)のとき、longjmp() で処理を強制的に抜ける。ところが、リクエスト用のメモリが初期化しきれていない途中でメモリ確保が失敗すると、壊れた状態のままリクエストの終了処理に進んでしまう。攻撃者は、post_max_size の範囲に収まる multipart リクエストで、各パートのヘッダーを大量に送ったり、空のファイル欄をネストさせたりして、意図的に memory_limit を使い切らせる。mod_php では、この一連の流れがアプリのコードの実行前に起きる。 CVE-2026-109619(GHSA-6wmf-4rv5-p3rp「RCE via stale global state」)。PHP のワーカーは、前のリクエストの状態をグローバル変数に持っていて、次のリクエストの前にリセットする。前のリクエストが致命的エラーで落ちるとそのリセットが飛び、解放済みのメモリを指したままの状態が残る。次のリクエストが通常の初期化より前にそれを触ると、use-after-free になる。確認されている経路のひとつが session upload progress で、これはデフォルトで有効、しかもアプリが session_start() を呼んでいなくても経路になる。 修正は両方まとめて1つのコミット("Avoid state corruption via bailout")に入っているので、どちらか片方だけ直す、という選択肢はない。 発見者の Wiz の記事では CVE 番号の割り当てが公式と逆になっている(upload progress の経路を 109618 としている)。この記事では公式の GHSA の割り当てに合わせた。 どの構成が危ないのか 公式の GHSA に書かれた内容を、実行方式(SAPI)ごとに表にした。 SAPI CVE-2026-109618 CVE-2026-109619 Apache + mod_php アプリに依存しない RCE を実証済み 実証済み PHP-FPM ソース解析上は影響あり。完全な攻撃はまだ実証されていない session upload progress 経由で実証済み。成功するかはアプリの処理内容にも左右される FrankenPHP アプリに依存しない攻撃が成立する可能性が高い デフォルト構成では未確認 LiteSpeed 可能性あり(未検証) 条件次第 デフォルトの memory_limit(128M)と post_max_size(8M)のままで RCE が成立したと書かれているので、デフォルト設定のままのサーバーもそのまま対象になると考えたほうがよく、Wiz も「Hello World だけのアプリでも影響を受けうる」と書いている。nginx + PHP-FPM の構成でも、アプリに依存しない攻撃がまだ見つかっていないだけで、安全が確認されたわけではない。実際、PHP Foundation のブログは、CVE-2026-109618 についても PHP-FPM でアプリ側の処理を経由した RCE を確認したと書いていて、GHSA の記述より一歩踏み込んでいる。 影響を受けるバージョンと直し方 公式の advisory が影響ありとしているのは、次の修正版より前のバージョンだ。 PHP 8.5.12 未満 PHP 8.4.27 未満 PHP 8.3.36 未満 PHP 8.2.35 未満 php.net の advisory が挙げているのはサポート中の 8.2〜8.5 だけだが、古いバージョンが安全という意味ではない。発見者の Wiz と Calif は PHP 5.4 以降のほぼすべてが影響を受けるとしていて、Google Cloud のセキュリティ情報も 5.4〜8.5 を対象として扱っている。PHP のセキュリティチーム自身も、サポートが終わった 7.4 / 8.0 / 8.1 向けにソースのパッチを用意していて、後述のとおり、ディストリビューションも古いバージョンに修正を入れている。 PHP 8.1 and older no longer receive updates from the PHP project. 対策は、上の修正版(またはディストリビューションの修正済みパッケージ)に更新することしかない。PHP の公式発表にも、はっきりそう書かれている。 There are no complete mitigations, updating is the only safe choice. バージョンを確認するときは、php -v で表示されるのが CLI の版だという点に注意したい。Web で実際に動いている PHP-FPM や mod_php が別のバージョンのこともあるので、php-fpm -v や、一時的に置いた phpinfo() で確かめるといい(確認したら phpinfo() は消しておく)。ディストリビューションによっては、コマンド名が php-fpm8.3 のようにバージョンつきになっている。更新したあとは、PHP-FPM や Apache を再起動しないと古いプロセスが動き続けるので、再起動まで済ませてほしい。 ディストリビューションのパッケージは、修正をバックポートしていてバージョン番号が upstream と一致しないことがあるので、その場合はパッケージの changelog に CVE 番号が載っているかで判断する。Docker の公式イメージには php:8.5.12-fpm などのタグが 10/22 未明(JST)に出ているが、php:8.4 のような浮動タグは pull し直さないと古いままだ。remi のリポジトリは、当日中には更新しないと告知されていた。 すぐ更新できないときの緩和策 公式は、いくつかの緩和策を挙げつつ、どれも「特定の攻撃経路を減らすだけで、安全にはならない」と念を押している。 If you cannot update immediately: while only an update is a complete solution, the following measures reduce exposure to specific attack paths but do not make an installation safe. 挙げられている主なものはこのあたりになる。 session.upload_progress.enabled=0 にして、全ワーカーを再起動する。php.ini や FPM のプール設定など、リクエストの解析より前に読み込まれる場所で設定する必要があり、ini_set() や .user.ini では意味がない。これで塞がるのは CVE-2026-109619 の確認済みの session 経路だけ。 PHP 8.5 では fatal_error_backtraces=0 にする。 memory_limit=-1 をアプリから上書きできない形で設定する。とはいえ、OS 側のメモリ確保失敗では同じ経路に入りうると書かれている。メモリの上限がなくなるので、サーバー全体のメモリを使い切られないよう、コンテナや cgroup の上限とあわせて使う。 post_max_size を下げ、フロント(リバースプロキシや WAF)でリクエストのサイズ、パーツ数、ヘッダー数を制限する。multipart を使わないアプリなら、フロントで multipart を止める。 パッチを当てたあとも、upload progress の機能を使っていないなら無効のままにしておくことを GHSA はすすめている。 ディストリビューションとホスティングの対応 主なディストリビューションは、10/21〜22 にかけて更新を公開している。バックポートで修正しているため、バージョン番号が upstream と違うものが多い。 提供元 修正版の例 備考 Debian trixie 8.4.27-1~deb13u1(DSA-6574-1)、bookworm 8.2.35-1~deb12u1(DLA-4848-1) forky / sid は修正版 8.4.27-1 がアップロード済みで、記事の時点では反映待ち Ubuntu 24.04 8.3.6-0ubuntu0.24.04.13、22.04 8.1.2-1ubuntu2.28 など 番号は古いままで修正入り RHEL 記事の時点で確認できたのは RHEL 8 の php:7.4 向けのみ ほかのストリームは AlmaLinux が先行して出している AlmaLinux 全ストリームで .alma.1 つきの版 Red Hat より先に出している Amazon Linux 2023 php8.2〜8.5 で ALAS2023-2026-3301〜3304 php8.1 と AL2 core は修正予定なし Alpine php83 8.3.36-r0、php84 8.4.27-r0、php85 8.5.12-r0 cPanel(CloudLinux) ea-php52〜ea-php85 を更新 ea-php84 は 8.4.26 のまま修正入り、と明記されている ondrej/php PPA 8.5.12-1 などに加え、5.6〜8.1 の EOL 版にも修正版 Docker 公式 php イメージ 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 のタグ 浮動タグは pull し直す AlmaLinux のブログにも、確認は php -v ではなくパッケージのバージョンで、と書かれている。RHEL 系なら rpm -q php-common、Debian 系なら dpkg -l | grep php でバージョンを調べ、changelog に CVE 番号が載っているかを確かめるのがいいと思う。 クラウドの PaaS も対応を進めていて、AWS は Elastic Beanstalk の PHP プラットフォームと Lightsail の blueprint の更新を案内している(Lightsail の既存インスタンスは作り直して移行する必要がある)。Google Cloud は App Engine や Cloud Run で、自動更新を有効にしていない場合は再デプロイが必要としている。Azure App Service(Linux)と Heroku も 10/21 に修正版を公開した。 国内のレンタルサーバーでは、さくらのレンタルサーバが 10/21 23:00〜10/22 06:30 の緊急メンテで PHP を更新し、ロリポップ!は予防措置として一部のサービスを止めてメンテナンスに入っていた。レンタルサーバーやマネージドの環境では事業者が対応することが多いが、古い PHP のバージョンを選んでいる場合は切り替えを求められることがあるので、管理画面のお知らせは見ておくと安心だと思う。 アプリ側では、WordPress が「WordPress 本体の更新は不要で、予定もない」と発表し、Drupal も PHP の更新が唯一の完全な対策だとしている。PHP2Shell は WordPress ではなくサーバー側の PHP の脆弱性なので、WordPress を最新版にしても対策にはならない。 WAF での暫定対応 Cloudflare は、修正版公開の約11時間前にあたる 10/21 12:02(日本時間)から、無料プランも含めてデフォルトで保護ルールを有効にしている。AWS WAF、Akamai、Fastly もルールを公開していて、AWS のブログでは、PHPSESSID と PHP_SESSION_UPLOAD_PROGRESS を両方含む POST を止めるカスタムルールが紹介されている。ただ、Cloudflare は攻撃者がペイロードを書き換えて回避を試みているとも報告しているので、WAF はあくまで更新までのつなぎと考えたほうがよさそうだ。 悪用はされているのか 悪用の状況は情報が錯綜しているので、攻撃の試行が観測された話と、侵入に成功した話を分けて読む必要がある。 AWS は、公開前の 10/17 からハニーポットで試行を観測していたと発表した。その試行が成功したかは不明としつつ、10/21 11:00(日本時間)ごろに PoC が出回ってからは試行が急増し、PHP2Shell はすでに広く悪用されている、と書いている。 Cloudflare、Patchstack、Hadrian、watchTowr なども、10/21 に試行を観測したと報告している。 一方で PHP Foundation は「公開時点で、実際の攻撃に使われている exploit は確認していない」としている。CISA の KEV(悪用が確認された脆弱性のカタログ)にも、記事の時点では載っていない。 記事の時点で、侵入に成功した具体的な事例の報告は見当たらない。とはいえ、PoC が出回って大量のスキャンが始まっている以上、更新していないサーバーは狙われている前提で動いたほうがいいと思う。 日本では、JPCERT/CC と IPA が 10/22 に注意喚起を公開した。海外では、CISA がすぐに更新できない場合や PHP 8.1 以前を使い続けている場合はシステムをオフラインにすべきだとし、英国の NCSC もオフラインにすることを検討するよう求めている。冒頭の高市首相の「ウェブサイト等を一時的に停止させることも有効策の一つ」という呼びかけも、同じ考え方になる。 まとめ エンジニアでない人は、まず第1部と第2部の冒頭のボックスに書いたことを確認してほしい。以下は、サーバーを自分で管理しているエンジニア向けの確認項目になっている。 eMudhra の件で確認すること。 テスト用ホストに、curl と、実際にアプリが使っている言語のクライアントで接続して、証明書エラーになるか確かめる OS の ca-certificates を更新する(macOS の /etc/ssl/cert.pem は未更新) Go / Rust / Deno のバイナリは修正版で再ビルドする。Node.js と Java は本体を更新し、Electron 製のアプリはアプリの更新を待つ Python は certifi と pip を更新する コンテナイメージは、ベースイメージを pull し直して作り直す 更新したら、長時間動いているプロセスを再起動する eMudhra の証明書を使っているサイトは、10/28 までに別の認証局の証明書に入れ替える PHP2Shell で確認すること。 PHP を 8.5.12 / 8.4.27 / 8.3.36 / 8.2.35 以上に更新し、PHP-FPM や Apache を再起動する(ディストリビューションのパッケージは changelog で CVE 番号を確認する) すぐ更新できないなら、session.upload_progress.enabled=0 などの緩和策を入れたうえで、できるだけ早く更新する 8.1 以前は、ディストリビューションの修正済みパッケージがあればまずそれを入れ、そのうえでサポートのあるバージョンへの移行を急ぐ 参考リンク eMudhra の件。 emudhra.we-have-a-problem.com Mozilla Bugzilla #2083449 Mozilla dev-security-policy のスレッド Google のブログ eMudhra の声明 PHP2Shell。 PHP の発表(php.net) GHSA-w8hw-w9fx-j79w(CVE-2026-109618) GHSA-6wmf-4rv5-p3rp(CVE-2026-109619) PHP Foundation のブログ Wiz の記事 Calif の記事

    1 like
  5. anyone using the #composer/#xdebug-handler and want to give this PR a try? the idea/question is, whether/when pcntl_exec is more efficient than running/wiring up a subprocess would be great this could be tested in more applications xdebug-handler#176

    1 like · 63 views
Trending awards, every completed day and week
Gold
51st place finishes
Silver
32nd place finishes
Bronze
03rd place finishes
Awarded repositories
1Owned by composer now

Repositories

Ordered by gold, then silver, then bronze.

  1. composerBest: 1st by forks, 1,311 forks530

A repository earns an award for finishing first, second or third in a completed trending day or week, ranked by new stars, new forks or pull request authors. Awards follow a repository through renames and transfers and count toward its current owner. Weeks run Monday to Sunday, UTC.