メインコンテンツへスキップ
見出し画像

文系かつ実務家寄りの人間がお伝えする、PHPは「止めた後」が危なかった話


    2026年10月21日、世界中のWebサイトが大変なことになったらしい。

    PHPというプログラミング言語に、重大な脆弱性が公表されたという。

    PHP。

    名前くらいは知っている。Webサイトの裏側で働いている、なかなか重要なプログラムである。

    なんでも、今回の欠陥を悪用すると、外部からサーバーを乗っ取ることができるらしい。

    なるほど。

    大変だ。

    しかし、どうしてそんなことができるのか。

    調べてみた。

    メモリ不足。異常終了。解放済みメモリ。Use After Free。リモートコード実行。

    ……。

    分からん。

    いや、個々の言葉の意味は、なんとなく分かる。

    だが、メモリが足りなくなったら、普通はプログラムが止まるんじゃないのか。

    止まったのに、どうして乗っ取られるんだ。

    ということで、今回もChatGPTさんに聞いてみた。

    なお、私はセキュリティの専門家ではない。プログラミングについても素人に毛が生えた程度である。
    毛量については、できれば触れないでいただきたい。
    毛量については、できれば触れないでいただきたい。
    (否、私はフサフサである。いいね?)

    ……以下は、そんな文系かつ実務家寄りの人間が、GPTさんと話しながら今回の事件を理解しようとした記録をもとにした解説である。






    まず、PHPって何なのか

    PHPは、Webサイトの裏側で動くプログラミング言語である。

    例えば、ネットショップで商品を検索する。会員情報を呼び出す。注文を受け付ける。

    そうした処理を、Webサーバー側で実行するために使われている。

    有名なWordPressもPHPで動いている。

    そして、ここが重要なのだが、PHPで書かれたプログラムを動かすには、それを読み取って実行するためのソフトウェア、実行環境が必要になる。

    この実行環境も、PHPと呼ばれている。

    つまり、Webサイトごとに書かれたプログラムは違っていても、それを動かしている仕組みは共通している場合がある。

    それぞれ違う車を作っていても、同じエンジンを搭載しているようなものだ。

    だから、ネットショップを作った人がどれほど正しくPHPプログラムを書いていても、そのプログラムを動かすPHP実行環境自体に問題があれば、影響を受ける可能性がある。


    我々が話す日本語に例えると、どれほど国語能力が高い人が話したとして、日本語自体に特定の組み合わせで必ず悪魔が呼び出されるとしたら、その組み合わせを口にしたら悪魔がやってくるのだ。そんな感じ。

    かえって分かりにくいか?
    あっ、GPTさんから「少し違う」と指摘が入りました。
    この喩えだとPHPプログラムの方になる? あっ。
    ……まぁ、取り敢えずいい。

    今回発見されたのは、そんなPHP実行環境の脆弱性だ。

    名前は「PHP2Shell」。

    貝殻……? 甲羅……? ほら、もう分からない。
    いや、そういう名前ってことで、まずは続けようか。


    しかも、問題となった脆弱性は二つあり、どちらも深刻度が非常に高い。

    では、何が起こるのか。



    総当たり攻撃じゃないの?

    最初に思ったのは、総当たり攻撃だった。

    パスワードを何度も試す。あるいは、大量のアクセスを送り込んでサーバーをダウンさせる。

    そういう類の攻撃かと思った。

    違った。

    今回の問題は、パスワードを突破することではない。

    サーバー自身に、本来してはいけない処理をさせてしまうことなのだ。

    これをリモートコード実行、略してRCEと呼ぶらしい。

    Remote Code Execution。
    遠隔からのコード実行。
    そのまんまだな。

    しかし、名前が分かっても、仕組みが分からない。

    いったい、どうやって他人のサーバーに勝手な処理を実行させるのか。

    そこで出てきたのが、メモリというものだった。



    メモリリーク?

    最初に思い浮かんだのは、メモリリークだった。

    プログラムが使い終わったメモリを解放し忘れ、使用量が増え続ける問題である。

    これは知っている。
    会社で、キャビネットから持ってきたファイルをいつまでも返さず、それどころか次々と持ってきて、机の上がいっぱいになったような状態だ。
    うん、この喩えはキマったな。


    しかし、GPTさんによると、今回の問題はそれとは違うらしい。

    一つ目は、メモリが足りなくなって処理を中断した際、作りかけのデータを正常なものとして扱ってしまう問題。

    二つ目は、メモリを解放したのに、その領域を指す情報が残ってしまい、後から再び参照する問題。

    ……。

    ちょっと待て。

    なんだ、その二つ目は。

    解放したメモリを、また使う?
    無いものを? 既に無いものを?
    消したのはキミだろう?

    それはまずいんじゃないのか。

    そして一つ目。

    メモリが足りなくなって処理を中断したのに、なぜ作りかけのデータを使うんだ?
    作りかけのものは作りかけのもの。使用には堪えないだろう。

    ここで、ようやく今回の事件の奇妙さが分かってきた。



    仕事を中止したのに、後始末で事故が起きる

    まず、一つ目の問題から考えてみよう。

    技術的には、CVE-2026-109618という脆弱性である。

    なんとも覚えにくい名前だ。
    もう覚えなくていい。私は忘れた。
    そんなことに脳のメモリを費やす必要はない。

    この問題のポイントは、異常を検知して処理を中断した後にある。

    メモリの確保に失敗した。

    PHPは異常を検知した。

    そこで、通常の処理を中断した。

    ここまではいい。

    問題は、その後の後始末である。

    例えば、PHPは、Webサイトから送られてきた情報を処理する際に、まずメモリ上にデータを置く場所を用意する。

    そして、「ここにデータが一件ある」と管理情報に記録し、実際のデータを登録していく。

    だが、管理情報には「データが一件ある」と記録したものの、肝心のデータの登録が終わっていない、という瞬間にメモリ不足が発生することがある。

    すると、処理が中断される。

    つまり、「一件あります」と先に記録して、肝心の一件を登録し終わる前に止まってしまった。

    ところが、後始末をするプログラムは、管理情報に「一件ある」と記録されているので、そこには正常なデータがあるものとして処理を進めてしまう。

    いや、登録が完了してから「一件あります」にしなさいよ。

    未完了の案件が完了扱いになっているうえに、取り消し処理までできていない、ということだ。

    ええ……?

    それ、後から問題になる気配がヒシヒシするよ。伝票処理なんかであるあるだけど。

    ええと。

    これを、実務に置き換えてみよう。そろそろ寸劇を入れてみたくなった。


    ある会社で、伝票を登録している。

    「新しい伝票を一件登録します」

    ——はい、登録件数を一件増やしました。

    「では、取引先と金額を入力して……あっ、エラーが出ました。登録を中止します」

    ——承知しました。後始末に回します。

    後始末担当者、登場。

    ——ええと、登録済みの伝票が一件ありますね。では、これを片付けましょう。まず取引先は……。

    「まだ入力してません」

    ——では金額は?

    「それもまだです」

    ——伝票は?

    「完成してません」

    ——でも、登録件数は一件になっていますよ?

    「件数だけ先に登録しちゃったんです」

    ——では、登録された一件はどこに?

    「ありません」

    ——あるって書いてあるじゃないですか!

    「だから、登録する途中でエラーになったんです!」

    ——だったら件数を戻してくださいよ!

    「戻してないんです!」

    ——なんで!? ……もういいです! 分からないけど、後始末を実行しちゃいます!


    ……。
    いや、だから、登録が完了してから『一件あります』にしなさいよ。
    そして、分からないなら実行しないで。


    本来なら、ここで作業を止めて確認するだろう。しかし、プログラムは管理情報を信用して処理を進めてしまう。

    何の処理を進めてるの、キミ。
    ああ、後始末か。

    なるほど、作りかけのデータを片付けようとするわけだ。

    ……。

    いや、作りかけのデータを、完成品と同じ手順で片付けちゃ駄目だろう。
    分別、ダイジ。

    もちろん、実際のPHPが伝票を処理しているわけではない。

    問題は、まだ正しく作り終えていないデータを、後始末のプログラムが正常なものとして扱い、いつもの手順でその中身を参照してしまうことだ。

    ……参照?

    消そうとしていたんじゃないのか?

    どうやら、データを消すときにも、そのデータが何なのかを調べる必要があるらしい。

    例えば、データの種類によって、後始末の方法が違う。単純な数値ならともかく、文字列や配列などには、それぞれ片付けるべきものがある。

    だから、まず種類を調べて、それに応じた片付け方をする。

    なるほど。捨てる前に分別するわけだ。

    ところが、今回の問題では、肝心の種類を示す情報がまだ正しく設定されていない。

    それなのに、そこを調べて、書かれている内容に従って片付けようとする。

    ……。

    いや、だから、その分別表示が正しいとは限らないんだって!

    分別、ダイジ。

    正しい分別、もっとダイジ。

    その結果、プログラムが異常な動作を起こす可能性がある。

    そして攻撃者は、まさにその異常を狙って、わざと問題を引き起こすようなデータを送り込む。

    つまり、単なるプログラムの不具合が、攻撃の手段になってしまうのだ。


    異常を検知して処理を止めたのに。



    退職者が仕事をしている

    続いて二つ目。

    こちらはCVE-2026-109619。

    Use After Free、解放後使用と呼ばれる問題につながる。

    この問題を理解するには、メモリを解放するという行為を少し考える必要がある。

    メモリを解放するとは、そこにあった物理的な領域が消滅することではない。

    その領域を、別の処理で使えるようにすることだ。

    例えば、会社の座席だと考えてみよう。

    ある社員が退職した。

    当然、その社員が使用していた席は空く。

    やがて新しい社員が入社し、その席を使うことになった。

    ところが、社内の座席表……管理台帳には、以前の社員の情報が残っていた。

    ある日、管理システムがその管理台帳を参照する。

    「この席にいるのは田中さんですね」

    「いいえ、田中さんは退職しました」

    「しかし、管理台帳には田中さんとあります」

    「今は佐藤さんが座っています」

    「いいえ。その席は田中さんの席です。田中さんに処理を依頼します」

    「だから、田中さんはいないんだって!」

    「その席に指示を送りました」

    「だから、そこにいるのは佐藤さんだって!」

    「……つーん」

    ねえ、聞いて。ちゃんと聞いて。



    今回の問題は、これに似ている。

    あるリクエストの処理が終わった。

    使用していたメモリは解放された。

    ところが、メモリ自体はきちんと解放されたのに、その場所を指し示す情報だけが、PHPの処理担当プロセスに残ってしまう場合がある。

    そして、同じプロセスが次のリクエストを受けたとき、その古い情報を使ってしまう。

    つまり、すでに別の用途に使われているかもしれない領域を、以前のデータが残っているものとして扱ってしまう。

    これがUse After Freeだ。

    お宝は既に掘り返されている。なのに、古い宝の地図を頼りに、同じ場所をまた掘り返しに行っている、というようなものだ。

    しかも、その場所には、既に別の誰かが別のもの——例えば産業廃棄物を埋めているかもしれない。

    掘り当てたとしても、それはもう、お前の宝じゃない。それどころか、毒を撒き散らすゴミかもしれない。

    なのに、それを宝だと思って持ち帰ってしまうのだ。


    もちろん、退職者の席に指示を送るだけなら、会社の中で少々混乱が起きる程度だろう。(……えっと、お宝の話は置いておいてね)

    しかし、コンピューターの内部で参照しているのは、単なる人名ではない。

    プログラムの動作を左右する情報である。

    攻撃者が、その場所に自分の用意したデータを配置できる状況を作り出せば、PHPの処理を、本来意図しない方向へ誘導できる可能性がある。

    なるほど。

    なるほど。

    もういないはずの人間を頼りに仕事を進めたら、いつの間にか別人の指示で動いていた。

    そういうことか。

    ……いや、そういうことか、ではない。

    ヤバいぞ、これ。ヤバヤバのヤバ。



    で、どうして乗っ取られるのか

    ここまでで、二つの問題はなんとなく分かった。

    しかし、疑問が残る。

    メモリの管理に問題があることと、サーバーを乗っ取られることは、別の話ではないのか。

    例えば、作りかけの管理情報を参照したせいで、プログラムがクラッシュする。

    それなら理解できる。

    古いメモリを参照して、変なデータを読み込んでしまう。

    それも理解できる。

    しかし、そこからどうして、攻撃者の命令を実行する話になるのか。

    ここが今回の攻撃の肝らしい。

    メモリの中には、単なる文章や数字だけでなく、「プログラムが次に何をするかを決める」ための情報も置かれている。

    本来、そうした情報は正しく管理されなければならない。

    ところが、今回の欠陥を利用すると、プログラムに、本来信用してはいけないメモリの内容を信用させることができるケースがある。

    そして攻撃者が、その内容やメモリの配置をうまく操作できれば、プログラムの実行の流れそのものを変えられる可能性がある。

    つまり、外部から、

    「この命令を実行してください」

    と正規の依頼をするのではない。

    プログラム自身が、誤った管理情報に従って、攻撃者に都合のよい処理を実行してしまう。

    ということらしい。

    これが成功すれば、データの読み取りや改ざん、不正なプログラムの設置などにつながる可能性がある。

    もちろん、メモリ管理の異常が発生すれば必ず乗っ取れるわけではない。

    プログラムが停止するだけの場合もあるし、攻撃を成立させるには環境や条件を揃える必要がある。

    しかし今回、研究者たちは、実際に遠隔からコードを実行できることを検証環境で示している。

    なるほど。

    単に「壊れる」という問題ではない。

    壊れ方を操作されると、攻撃者の望むように動かされてしまう。

    そういうことなのだ。



    サイバーパンクの世界じゃないのか

    ここまで聞いて、妙な既視感を覚えた。

    SFやサイバーパンクもので、こういう攻撃を見たことがある気がする。

    敵のシステムに異常を起こさせる。

    システムが停止する。

    復旧処理が始まる。

    その復旧処理の隙を突いて、攻撃プログラムを紛れ込ませる。

    そういう、いかにも凄腕ハッカーがやりそうな攻撃だ。

    今回の問題も、それに似ている。

    ただし、厳密には少し違うらしい。

    サーバー全体をダウンさせて再起動させる必要はない。

    通常のリクエスト処理の中で発生する異常や、処理が終わって次のリクエストへ移る際の不整合を利用する。

    だから、何も映画のように巨大なシステムを停止させる必要はない。

    インターネット経由で、特殊なリクエストを送り込むだけで攻撃のきっかけを作れる場合がある。

    しかも、ログインすら必要としないケースがあるという。

    ……。

    サイバーパンクのハッキングというと、妙に派手な画面で大量の文字列が流れ、黒い背景に緑色の文字で「ACCESS GRANTED」とかなんとか表示される印象がある。

    実際には、Webサーバーの裏側でメモリ管理の整合性が崩れる。

    地味だ。しかし、結果は派手である。

    演出は地味だが、被害はパンクだった。エッジを攻めてる。



    そして、ここにもAIが出てくる

    今回の事件には、もう一つ興味深い点がある。

    AIだ。

    今回の脆弱性の発見と攻撃可能性の検証には、AIを活用した研究が大きく関わっている。

    セキュリティ企業のWizは「複数のAIモデルを利用して、PHPに潜んでいた欠陥を発見し、攻撃として成立することを確認した」と説明している。

    ただし、誤解してはいけない。

    今回の欠陥は、AIが作ったものではない。
    AIが勝手にPHPのサーバーへ侵入したという話でもない。

    欠陥自体は以前から存在していた。

    問題は、その欠陥を実際の攻撃に利用できると証明するまでが、従来は非常に難しかったことにある。

    メモリの使われ方を調べる。
    異常が発生する条件を探す。
    プログラムの動きを分析する。
    試してみる。
    失敗する。
    条件を変える。
    また試す。

    こうした作業には、高度な専門知識と相当な試行錯誤……試行回数が必要になる。

    そこでAIの出番である。

    AIが解析や試行錯誤を支援し、ときにはその一部を肩代わりすることによって、従来は困難だった欠陥の発見や攻撃の実証が、現実的になり始めている。

    もちろん、これは防御側にとっても大きな利益だ。

    人間が気付かなかった問題を、AIの助けを借りて発見し、修正できるのだから。

    しかし、同じ技術を攻撃者も利用できる。

    つまり、

    「欠陥はあるけれど、攻撃として利用するのは難しい」

    という状態が、今後は安全の根拠にならなくなるかもしれない。

    そう考えると、これは単にPHPだけの問題ではない。

    AIがサイバーセキュリティの世界に、どんな変化をもたらすのか。

    その一端を見せつけ、実証した事件でもあるのだろう。



    では、どうすればいいのか

    幸い、今回の二つの脆弱性については、PHPの開発元が修正版を公開している。

    2026年10月24日現在、PHP 8.2から8.5の各系列で、問題に対応したバージョンが提供されている。

    Webサイトの運営者は、PHPの利用状況を確認し、必要な更新を行うことが重要になる。

    一方、普通にWebサイトを閲覧しているだけの利用者が、自分のパソコンやスマートフォンでPHPを更新する必要は基本的にない。

    問題の中心は、サーバー側で動いているPHPだからだ。
    そもそも、見てるだけなら使ってないよね、PHP。

    そして、今回の事件について報告されている攻撃の試みと、実際にサーバーへの侵入が成功した事例は、区別して考える必要がある。

    脆弱性がある。

    攻撃を試みる者がいる。

    攻撃として成立することが実証されている。

    これらは重大な話だが、すべてのPHPサーバーが無条件に乗っ取られてしまうわけではない。

    そこは冷静に考えていい。



    さて、実務家としては

    ここまで調べてきて、ようやく今回の問題が少し分かった気がする。

    そして、今回の事件で最も印象に残ったのは、実はメモリでもAIでもない。

    異常を検知できることと、異常が発生した後に安全に処理できることは、同じではない。

    ということだ。

    我々実務家は、仕事がうまくいかなくなったとき、どうするかを日々考えている。

    問題が発生したら報告する。
    作業を中断する。
    関係者へ連絡する。
    未処理の案件を整理する。
    必要なら原状回復する。
    そして、再発防止策を考える。

    そういう手順がある。

    しかし、考えてみれば、そこには一つの前提がある。

    異常が発生した後でも、後始末の手順は正常に動く。

    という前提だ。

    今回の事件は、その前提を突いてきた。

    正常に動いているときは問題がない。
    異常を検知することもできる。
    しかし、異常が発生した後の処理が安全であるとは限らない。

    そして、その後始末自体が、新しい問題を生んでしまう。

    ……。

    なんだか、身に覚えのある話である。

    トラブルが発生した。
    作業を止めた。
    事態を収拾するため、関係者が集まった。
    会議を開いた。
    対策を検討した。
    新しいルールを作った。
    そして、後始末の会議でさらに問題が増えた。

    ……。

    いや。

    PHPだけの話ではないような気がしてきたな。




    参考資料


    ※本文中の業務上のたとえ話は、技術的な仕組みを理解しやすくするための比喩であり、実際のプログラムの動作をそのまま表現したものではありません。



     
     

    Capybarian

     
     
    ブログ文化の系譜。 テキストサイト文化の末裔。 中二病と大二病を引きずったまま社会人になって幾歳月。 noteでは変な記事を掲載しています。 交流は控えめ。だけど、スキしてもらったらホイホイと見に行きます。

    あなたへのおすすめ