
「PHP2Shell」の攻撃POSTを解析、中身はサーバーをDDoS攻撃の踏み台にするボットの取得命令
PHP2Shellは、2026年10月21日に公表されたPHPの重大な脆弱性群の呼び名だ。攻撃が成立すると、Webサーバー上で攻撃者のコードが実行される。今回、我々が観測用に公開していたPHPサーバーに届いた攻撃が実行させようとしていたのは、他のサーバーへ大量通信を送るDDoSボットだった。
User-Agentはphp2shell-109618。POSTの本文には外部スクリプトの取得・実行命令があり、配布先から取得した実行ファイルには、指示を受けてUDPパケットを繰り返し送る処理があった。2026年10月22日の通信記録とバイナリの解析から、サーバーに何をさせようとしていたのかを追う。
攻撃が通ると、PHPサーバーは何に使われるのか
届いた命令は、外部のスクリプトを取得し、そこからnfsという実行ファイルを起動させる内容だった。nfsには、攻撃者側の指示に応じて大量通信を行う機能が入っていた。PHPサーバーを乗っ取り、他の相手への攻撃に使う狙いだ。
DDoSボットは、感染したマシンを大量通信に使うプログラムだ。多数のマシンが指定された相手へ一斉に通信し、回線や処理能力を消費する。自社サーバーが、他社のサービスを妨害する送信元にされるおそれがある。
PHP2Shellを名乗るPOSTが届いた
10月22日22時01分と22時38分、同じ送信元からPOSTが届いた。最初は/index.php、次はPHPUnitのeval-stdin.phpを探すパスだった。時刻は日本時間で記す。
2026-10-22 22:01:03 JST POST /index.php → 200
2026-10-22 22:38:44 JST POST /lib/phpunit/phpunit/Util/PHP/eval-stdin.php → 404
User-Agent: php2shell-109618
Content-Type: multipart/form-data
Content-Length: 62929保存したパケットをTCPの順番に並べて本文を復元すると、2件とも実長は62,929バイトで、本文のハッシュも一致した。異なるパスへ同じ本文を送っていた。約63KBの中に、アップロード進捗用の項目、ファイル用の項目、繰り返し並ぶバイナリ値があった。
そのバイナリ値の中に、systemという文字列と、外部スクリプトの取得結果をシェルへ渡す命令が埋まっていた。OS上でプログラムを実行させようとするPOSTだ。
なぜ、multipartでPHPを攻撃できるのか
今回のUser-Agentにある109618は、CVE-2026-109618に対応する。PHP公式は、メモリ不足で不正なメモリ状態が残り、遠隔からコードを実行される問題として説明している。
multipartは、フォームの値やアップロードするファイルを、一つのHTTP本文の中で区切って送る形式だ。PHPはその本文を読み、項目やファイルの情報をメモリ上に作る。入力の構造によっては、通信で届いたバイト数より多くのメモリを消費する。
メモリ不足からコード実行につながる仕組み
Apacheのmod_phpでは、Webアプリ固有のコードが始まる前の本文解析も攻撃の入口になり得る。
関連するCVE-2026-109619には、前のリクエストの状態が残り、次のリクエストが参照する問題もある。アップロード進捗の処理は、通常の初期化より早くセッションへ触れる経路になる。今回の本文にも、進捗用の項目が含まれていた。
我々は修正前のPHP8.3.35と、修正を含むPHP8.3.36を別々の仮想マシンで公開していた。今回の2件はPHP8.3.35で受信した。
配布先には、短いスクリプトが置かれていた
本文の命令が指定する配布先には、次のスクリプトが置かれていた。取得時の画面だ。
一行の中に、/tmpへの移動、nfsの取得、chmodでの実行権限付与、起動までが続いている。末尾のx86_64は、nfsに渡す引数だ。最初のスクリプトが、別の実行ファイルを取得して起動する役割を持っていた。
続いてnfsをファイルとして取得し、実行せずに形式を確認した。
$ file data/specimen/nfs
data/specimen/nfs: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
$ sha256sum data/specimen/nfs
0c5486f06620e26e316f4b33f318b0d646d5e1133789331aa2fed012360d1486 data/specimen/nfsサイズは179,632バイト。ELFというLinuxなどで使う実行ファイル形式で、CPUの種類はx86-64だった。配布スクリプトがnfsに渡していた引数と一致する。関数名などのシンボル情報は取り除かれていた。
バイナリを開くと、DDoSボットの処理が見つかった
実行ファイルを動かさず、命令や埋め込みデータを調べる方法を静的解析という。今回は機械語を読める命令表記へ変える逆アセンブルと、埋め込み文字列の復号を組み合わせた。
文字列を拾うだけでは、通信先の大半が見えなかった。命令を追うと、文字列を暗号化して保存し、使用時に復号する処理があった。暗号処理はChaCha20に一致する構造だった。その規則を保存データに適用すると、接続先や通信に使う文字列が現れた。接続先の一つは指令サーバーで、ボットへ実行内容を指示する役割を持つ。
| 確認した処理 | 読み取れる用途 |
|---|---|
| 埋め込みドメインの解決と接続先の選択 | 外部の指令サーバーへ接続するための設定 |
| 受信した指示を24種類の処理へ振り分け | 指示に応じて実行する機能を選ぶ |
| UDPパケットを繰り返し送信 | 指定された相手へ通信を集中させる機能 |
| バックグラウンド化とプロセス名の変更 | 動作を続け、表示される名前を変える |
この検体は外部から受けた指示を処理へ振り分け、UDPという通信方式でパケットを繰り返し送信する機能を持っていた。これらが、DDoSボットと判断する根拠になった。
攻撃は成功したのか
- 通信本文:攻撃用の命令を受信した。 保存パケットから、外部スクリプトの取得・実行を指示する本文を復元した。
- 配布ファイル:DDoSボットの機能を確認した。 別途取得したnfsを静的解析し、指示の受信とUDPの反復送信を確認した。
- サーバー上で、不正なコマンドが実行された形跡はなかった。 10月22日23時台に調べたOSの監査ログでは、今回のPOSTに対応する外部コマンド実行は記録されていなかった。PHPの致命的エラーやメモリ不足の記録もなかった。
観測環境では、PHPコンテナから外部への新しい接続を遮断し、OSの操作記録と通信パケットを保存していた。最初のPOSTにはHTTP200で通常ページが返っていた。
自社システムの脆弱性対応やセキュリティ対策について、お気軽にご相談ください。




