1. ホーム
  2. ブログ
  3. PHP のセキュリティ

PHP2Shell の検知と多層防御|WAF・IDS(Suricata/Sigma/ModSecurity)・EDR・コンテナの硬化まで

公開
著者
編集部

修正版を入れるまでの間、何層で止め、どこで気づくか。CDN・WAF、Web サーバーの制限、PHP と FPM の設定、cgroup・seccomp、IDS・Sigma・EDR・SIEM の相関まで、PHP2Shell に合わせた多層防御を技術者向けにまとめた。

この記事の流れ約45秒
この記事で分かること

PHP2Shell の検知と多層防御|WAF・IDS(Suricata/Sigma/ModSecurity)・EDR・コンテナの硬化まで

  • 層は5つ。CDN・WAF、Web サーバー、PHP と FPM、実行環境(コンテナ・カーネル)、検知と対応
  • multipart を使わないアプリなら、手前で multipart を止めるのが効く(公式の勧告)
  • ModSecurity は multipart のとき REQUEST_BODY が空になり、本文を見るルールが発火しない落とし穴がある
  • いちばん確かな検知は「PHP のワーカーがシェルを起動した」という子プロセスの記録
1 / 8

全体像

どの層も、単独では不完全だ

ここを読む
PHP2Shell の多層防御
2 / 8

1. CDN・WAF

ここを読む
3 / 8

2. Web サーバーの制限

OOM を起こしにくくするため、PHP に届く前に、本文とヘッダーの大きさを絞る

ここを読む
4 / 8

3. PHP と FPM の設定

  • session.upload_progress.enabled=0:109619 のセッションの経路をふさぐ
  • fatal_error_backtraces=0(8.5):109619 のもっとも強い経路をふさぐ
  • memory_limit=-1(管理者の設定で固定):109618 の既知の経路を止める
ここを読む
5 / 8

4. 実行環境の硬化

RCE が成功しても、被害を小さくする層だ

  • cgroup の memory.max:コンテナやサービスのメモリの上限。完全な対策ではないが、暴走を抑える
  • 読み取り専用のルートファイルシステム:書き込みを、アップロードの場所と一時ファイルの場所だけにする。その場所では PHP を実行させない
  • seccomp・AppArmor・SELinux:ワーカーが execve で外のプログラムを起動できないようにする
ここを読む
6 / 8

5. 検知と対応

ここを読む
攻撃されたか確かめるとき、ログで見る所
7 / 8

優先順位

  • 1:修正版への更新(配布元のパッケージなら、更新と再起動)
  • 2:CDN・WAF のマネージドルールの確認と、オリジンの直接到達の遮断
  • 3:upload_progress・fatal_error_backtraces の無効化、本文の上限
ここを読む
8 / 8

用語

  • 多層防御:1つの対策に頼らず、複数の層を重ねる考え方
  • 仮想パッチ:本体を直す前に、WAF などで攻撃の形を止めること
  • オリジン:CDN の後ろにある、本物のサーバー
ここを読む

PHP2Shell の根本の対策は、修正版への更新だけだ。ただ、検証やメンテナンスの枠の都合で、すぐには入れられない環境もある。そのあいだ、何層で止め、どこで気づくか。公式の勧告と、公開されている検知のルールをもとに、多層防御(defense in depth)の組み立て方をまとめた。

この記事の要点
  • 層は5つ。CDN・WAF、Web サーバー、PHP と FPM、実行環境(コンテナ・カーネル)、検知と対応
  • multipart を使わないアプリなら、手前で multipart を止めるのが効く(公式の勧告)
  • ModSecurity は multipart のとき REQUEST_BODY が空になり、本文を見るルールが発火しない落とし穴がある
  • いちばん確かな検知は「PHP のワーカーがシェルを起動した」という子プロセスの記録
  • 公開されている検知のルールは非公式。検証の環境で試してから入れる

全体像

PHP2Shell の多層防御
PHP2Shell の多層防御

どの層も、単独では不完全だ。WAF はすり抜けがありうるし、PHP の設定は特定の経路しかふさがない。層を重ねて、更新までの時間をかせぎ、すり抜けたものを検知で拾う。

1. CDN・WAF

マネージドルール(仮想パッチ)

Cloudflare などの CDN は、PHP2Shell 向けのマネージドルールを急いで配った。報告によると、Cloudflare は無料のプランを含めて規則を入れている。CDN を通しているなら、マネージドルールが有効になっているか、ログで発火しているかを確かめる。

オリジンへの直接の到達をふさぐ

WAF は、オリジン(本物のサーバー)の IP に直接届く通信には効かない。オリジンのファイアウォールで、CDN の IP の範囲以外からの 80・443 番を閉じておく。

multipart を止める

公式の勧告(109618)は、アプリが multipart/form-data を使わないなら、手前で止めるよう勧めている。ファイルのアップロードがない API や、管理画面だけが multipart を使うサイトなら、パスごとに許可する形にできる。

2. Web サーバーの制限

OOM を起こしにくくするため、PHP に届く前に、本文とヘッダーの大きさを絞る。

nginx の例:

# 本文の上限(アップロードが要らないなら小さく)
client_max_body_size 8m;
# ヘッダーの大きさの上限
large_client_header_buffers 4 8k;

Apache の例:

# 本文の上限(バイト)
LimitRequestBody 8388608
# ヘッダーの数と1つの長さ
LimitRequestFields 50
LimitRequestFieldSize 8190

値はアプリに合わせる。小さくしすぎると、正規のアップロードやフォームが失敗する。

3. PHP と FPM の設定

設定狙い注意
session.upload_progress.enabled=0109619 のセッションの経路をふさぐ進み具合の表示を使うアプリでは動かなくなる
fatal_error_backtraces=0(8.5)109619 のもっとも強い経路をふさぐ
memory_limit=-1(管理者の設定で固定)109618 の既知の経路を止めるメモリを使い切る危険。長くは続けない
post_max_size を控えめに本文の解析の量を減らす
max_input_nesting_level を下げる入れ子の項目名による OOM を起こしにくくする既定は 64
max_input_vars・max_file_uploads を絞る項目数・パート数を絞る
pm.max_requests=1(FPM)1回ごとにワーカーを作り直し、状態の持ち越しをなくす性能が大きく落ちる。負荷の低いサイト向け

設定は php.ini か、FPM のプールの php_admin_value、Apache の php_admin_value で行い、すべてのワーカーを再起動する。ini_set() や .user.ini では効かない。

RLIMIT_AS・RLIMIT_DATA は使わない

プロセスのメモリの上限を RLIMIT_AS や RLIMIT_DATA でかけると、攻撃に必要な確保の失敗を、かえって起こしやすくする。公式の勧告も使わないよう書いている。上限は cgroup でかける。

4. 実行環境の硬化

RCE が成功しても、被害を小さくする層だ。

  • cgroup の memory.max:コンテナやサービスのメモリの上限。完全な対策ではないが、暴走を抑える
  • 読み取り専用のルートファイルシステム:書き込みを、アップロードの場所と一時ファイルの場所だけにする。その場所では PHP を実行させない
  • seccomp・AppArmor・SELinux:ワーカーが execve で外のプログラムを起動できないようにする
  • 外向きの通信の制限(egress):ワーカーから外への接続を、必要な宛先だけにする。逆接続のシェルや、追加の荷物の取得を止める
  • disable_functions:exec・system・passthru・shell_exec・proc_open・popen などを止める。ただし、メモリの破壊からの RCE は PHP の関数を経由しないことがあるので、これだけには頼らない
  • 秘密情報の置き場所:環境変数や設定ファイルの秘密は、ワーカーの権限で読める。侵害が疑われたら、鍵と資格情報を入れ替える

5. 検知と対応

攻撃されたか確かめるとき、ログで見る所
攻撃されたか確かめるとき、ログで見る所

ネットワーク(IDS・WAF のログ)

コミュニティから、Suricata・Snort・ModSecurity・Sigma のルールが公開されている。シグネチャの数や SID はリポジトリごとに違い、互いに入れ替えられるものではない。見ているのは、おおむね次の特徴だ。

  • 項目名が数 MB ある application/x-www-form-urlencoded の本文
  • 名前が空の項目にバイナリが入った multipart
  • PHP_SESSION_UPLOAD_PROGRESS を含む POST
  • PoC の既定の User-Agent
ModSecurity の落とし穴

公開されている検知の解説によると、ModSecurity は multipart の本文のとき REQUEST_BODY が空になる。本文を REQUEST_BODY で見る形のルールは、multipart では発火しない。早い時期に入れた本文ベースのルールは、見直しが要る。

ホスト(EDR・監査ログ)

いちばん確かな検知は、子プロセスの記録だ。Web のワーカー(php-fpm・apache2・httpd・php-cgi)が、sh・bash・dash を起動するのは、ふつうのアプリではまず起きない。Sigma の process_creation のルールなら、次のような形になる。

title: Web の PHP ワーカーからのシェルの起動
logsource:
  category: process_creation
  product: linux
detection:
  parent:
    ParentImage|endswith:
      - '/php-fpm'
      - '/apache2'
      - '/httpd'
      - '/php-cgi'
  child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
  condition: parent and child
level: high

PHP-FPM のマスターの名前は、配布元で php-fpm8.3 のように版が付くことがある。環境に合わせて名前を足す。アプリが正規に外のコマンドを呼ぶ場合(画像の変換など)は、例外として登録する。

SIEM での相関

単独では弱い手がかりも、同じ時刻・同じワーカーで重なれば強くなる。

手がかり出る場所
異常に大きい POST・multipartアクセスログ・WAF
Allowed memory size ... exhausted と「Unknown on line 0」PHP のエラーログ
ワーカーの異常終了(Apache の AH00052)Web サーバーのエラーログ
直後の HTTP 500アクセスログ
異常に長い PHPSESSID の Set-Cookie応答のログ(取っていれば)
ワーカーからの子プロセス・外への通信EDR・監査ログ・ファイアウォール

Datadog は、攻撃が HTTP 200 を返したままワーカーを動かし続けることがあると指摘している。状態の番号だけで判断しない。

優先順位

順やること効き目
1修正版への更新(配布元のパッケージなら、更新と再起動)根本の対策
2CDN・WAF のマネージドルールの確認と、オリジンの直接到達の遮断手前で大半を止める
3upload_progress・fatal_error_backtraces の無効化、本文の上限既知の経路をふさぐ
4子プロセスの検知(Sigma・EDR)すり抜けに気づく
5侵害の調査と、鍵・資格情報の入れ替え入られていた場合の後始末

用語

用語意味
多層防御1つの対策に頼らず、複数の層を重ねる考え方
仮想パッチ本体を直す前に、WAF などで攻撃の形を止めること
オリジンCDN の後ろにある、本物のサーバー
IDS侵入の兆しを通信から見つける仕組み(Suricata・Snort など)
Sigmaログの検知ルールを、製品に依存しない形で書く決まり
EDR端末やサーバーの動き(プロセス・通信)を記録し、不審な動きを見つける仕組み
SIEM複数のログを集め、組み合わせて分析する仕組み
egressサーバーから外へ出ていく通信

よくある質問

WAF を入れていれば更新しなくても大丈夫ですか?

大丈夫ではありません。
WAF はすり抜けがありえますし、オリジンに直接届く通信には効きません。
更新までのつなぎとして使ってください。

disable_functions で exec などを止めれば防げますか?

被害を小さくする効果はありますが、防ぎきれません。
メモリの破壊からのコードの実行は、PHP の関数を経由しないことがあるからです。

いちばん確実な検知の方法は何ですか?

Web の PHP のワーカーが、シェル(sh・bash など)を子プロセスとして起動した記録です。
ふつうのアプリではまず起きないので、誤検知が少なく、強い手がかりになります。

無料ツールPHP2Shell の無料診断PHP のバージョンとサーバー会社を選ぶだけで、危険度と今やることが分かります。

参考にした情報

この記事の情報

2026年10月22日時点の公開情報にもとづく。攻撃のコード(PoC)の中身は、悪用を助けないよう載せていない。最新の情報は、PHP の公式の勧告と JPCERT/CC を確認すること。

自社のサーバーの構成で、どの層から手を付けるべきかを、構成を聞いてから伝える。相談は無料。

無料で相談する

この記事の著者

編集部