Web サーバーのアクセスログを開くと、/wp-login.php、/xmlrpc.php、/phpinfo.php といった、身に覚えのない URL へのアクセスがずらりと並んでいることがあります。「攻撃されているのでは」と不安になって相談をいただくことの多い光景です。

結論:これらの大半は、インターネット上のサーバーに片っ端から同じリクエストを送る、機械的な探索です。届くこと自体は防げませんし、多くは 404 で終わります。大事なのは、探索が「当たる」もの — 不要なファイル、古いソフトウェア、公開してはいけないディレクトリ — をサーバーに置かないことです。本記事では、代表的なリクエストの正体と、Windows の日本語環境で特に注意が必要な CVE-2024-4577、ログの読み方と Web サーバー側の防御を整理します。

PHP を使っていなくても、攻撃は毎日届く

参考までに、当社が運用している Web サーバーの例を紹介します。このサーバーで動いているのは Node.js と静的ファイルのサイトだけで、PHP で書かれたページは 1 つもありません。それでも直近 7 日間のアクセスログを集計すると、全リクエストの約 16%、約 1.2 万件が PHP を狙った探索でした。

攻撃する側は、相手が PHP を使っているかどうかを確かめずにリクエストを送ってきます。つまり、サイトの規模や知名度に関係なく、公開されたサーバーにはすべて届くということです。「うちは小さな会社だから狙われない」は成り立ちません。

よく届くリクエストと狙い

リクエスト先狙い当たってしまう条件
/wp-login.phpWordPress 管理画面へのパスワード総当たり推測しやすいパスワード、ログイン試行の制限なし
/xmlrpc.php1 回のリクエストで大量のパスワードを試す、他サイトへの攻撃の踏み台XML-RPC を使っていないのに有効のまま
/phpinfo.php、/info.phpPHP のバージョンや設定、サーバーのパスを調べる動作確認で置いたファイルの消し忘れ
/vendor/phpunit/…/eval-stdin.php任意のコードを実行する(CVE-2017-9841)開発用ライブラリを公開ディレクトリに置いている
/.env、/.git/configデータベースやメールのパスワード、ソースコードを盗む設定ファイルや .git が公開ディレクトリにある
/backup.zip、/db.sql などバックアップファイルを丸ごと取得するバックアップを公開ディレクトリに置いたまま
URL に %AD と -d を含む php-cgi へのリクエスト任意のコードを実行する(CVE-2024-4577)Windows 上で PHP を CGI として動かしている

共通しているのは、どれも「置いてはいけないものが置いてある」「古いものが古いまま」のときにだけ成功するということです。逆に言えば、この表の右の列をひとつずつ潰していけば、大半の探索は空振りに終わります。

CVE-2024-4577 — Windows の日本語環境で起きる PHP の脆弱性

2024 年 6 月に公表された CVE-2024-4577 は、日本企業にとって特に注意が必要な脆弱性です。深刻度は CVSS 9.8(最大 10)で、公表直後から実際の攻撃に使われました。

何が起きるのか

Windows には、文字コードを変換するときに「似た文字」に置き換える仕組みがあります。日本語(コードページ 932)や中国語の環境では、この置き換えによって、URL に含めた特定の文字が PHP のコマンドライン引数の記号「-」として解釈されてしまいます。その結果、PHP を CGI として動かしているサーバーでは、外部から PHP の設定を書き換え、任意のコードを実行できてしまいます。2012 年に修正された CVE-2012-1823 の対策を、この文字変換で回避する形の脆弱性です。

影響を受ける環境

  • Windows 上で動いている PHP であること
  • PHP を CGI モードで動かしている、または php-cgi.exe が Web から呼び出せる状態であること
  • システムの言語が日本語・中国語(簡体字・繁体字)など、特定のコードページであること

特に、開発用の統合環境として広く使われている XAMPP の Windows 版は、初期設定のままで影響を受ける構成でした。「社内の Windows サーバーに XAMPP で業務アプリを入れて、そのまま外部公開している」という環境は、今すぐ確認してください。

対策

  • PHP を修正版(8.1.29 / 8.2.20 / 8.3.8 以降)に更新する。サポート切れの 8.0 以前には修正が提供されていないため、サポート中のバージョンへの移行が必要
  • CGI モードをやめ、PHP-FPM などの方式に切り替える
  • XAMPP などの開発用パッケージを、本番の公開サーバーとして使わない

phpunit の eval-stdin.php が今も狙われる理由

PHPUnit は PHP のテスト用ライブラリです。古いバージョンに含まれていた eval-stdin.php というファイルは、送られてきた内容を PHP のコードとして実行してしまう作りでした(CVE-2017-9841)。修正から何年も経っていますが、今も毎日のように探索が届きます。

理由は、Composer でインストールしたライブラリの置き場所(vendor/)を、公開ディレクトリの中にそのまま置いているサイトが今も残っているからです。テスト用のライブラリは本番に不要なので、composer install --no-dev で入れないようにし、vendor/ 自体を公開ディレクトリの外に置くのが正しい構成です。

ログの読み方 — 200 が返っていても侵入とは限らない

アクセスログの 1 行には、日時、接続元、リクエスト先、ステータスコード、レスポンスのサイズが記録されています。攻撃リクエストを見つけたら、まずこの 2 つを確認します。

  • 404 / 403:ファイルが存在しない、または拒否された。攻撃は空振り
  • 301 / 302:別の URL に転送された。転送先を確認すれば多くは問題なし
  • 200:何かが返った。ここだけは中身を確認する

ただし、200 だからといって侵入されたとは限りません。React や Vue で作ったサイト(SPA)では、存在しない URL にもトップページの HTML を返す設定が一般的で、/wp-login.php へのリクエストにも 200 が返ります。レスポンスのサイズがトップページと同じなら、この「誤報」である可能性が高いでしょう。当社のサーバーでも、200 が返っていた PHP 探索を調べると、すべてこのパターンでした。

一方、サイズがトップページと違う、POST に 200 が返っている、見覚えのない .php ファイルへのアクセスに 200 が返っている場合は要注意です。ファイルの改ざんや Web シェルの設置が疑われるため、サーバーのファイル一覧と更新日時を確認し、必要なら専門家に調査を依頼してください。

Web サーバー側でできる防御

狙われやすいパスを一括で拒否する

nginx の場合、次のような設定で隠しファイルや開発用ディレクトリへのアクセスをまとめて拒否できます。

# .env や .git などの隠しファイル(Let's Encrypt の認証用は除く)
location ~ /\.(?!well-known/) {
    deny all;
}

# 公開ディレクトリに置くべきでないディレクトリ
location ~* ^/(vendor|node_modules)/ {
    deny all;
}

# WordPress で XML-RPC を使っていない場合
location = /xmlrpc.php {
    deny all;
}

ただし、これは「置いてしまったときの保険」です。本来は、こうしたファイルを最初から公開ディレクトリに置かない構成にすることが先です。

総当たりを自動で止める

同じ接続元から短時間に大量の失敗が続いたら、一定時間ブロックする仕組みを入れておくと、パスワード総当たりやログの肥大化を抑えられます。Linux サーバーでは fail2ban が定番です。WordPress なら、ログイン試行回数を制限するプラグインや、管理画面への IP 制限も有効です。

ソフトウェアを更新し続ける

結局のところ、探索の多くは「古いバージョンのままの何か」を探しています。PHP 本体、CMS、プラグイン、ライブラリを更新し続けることが、どの設定よりも効きます。コード自体に潜む穴については PHP でよくある脆弱性 7 つと対策 を参照してください。

使っていない PHP は、消すのがいちばんの対策

サーバーの点検をしていると、使われていない PHP がインストールされたまま残っていることがあります。昔の動作確認で入れたもの、サーバー会社の初期構成に含まれていたもの、移行前のシステムの名残などです。

当社のサーバーでも、点検の結果、一度も起動されていない PHP の実行環境が残っていることが分かりました。Web からは使われておらず、すぐに悪用される状態ではありませんでしたが、更新もされておらず、設定ひとつで攻撃対象になりうる状態です。依存関係を確認したうえで、パッケージと関連する Web サーバー設定をまとめて削除しました。

使っていないソフトウェアは、更新する手間がかかるだけで、何の役にも立たない攻撃対象です。「使っているか分からないから残しておく」ではなく、使っていないことを確認して消す — これがもっとも確実で、費用もかからない対策です。

よくあるご質問

WordPressを使っていないのに wp-login.php へのアクセスが来るのはなぜですか?

攻撃の多くは、相手のサイトの中身を確かめずに、インターネット上のサーバーへ片っ端から同じリクエストを送る機械的なものだからです。WordPressを使っていなければ 404 が返るだけなので、それ自体は心配いりません。

攻撃リクエストに200が返っているのは、侵入されたということですか?

必ずしもそうではありません。存在しないURLにもトップページを返す設定のサイト(SPAなど)では、攻撃リクエストにも 200 が返ります。レスポンスのサイズがトップページと同じかどうか、そのURLに実際にファイルがあるかを確認してください。判断が難しい場合は専門家に相談することをおすすめします。

攻撃元のIPアドレスを1つずつブロックすれば防げますか?

効果は限定的です。攻撃元は大量にあり、日々入れ替わります。IPの手動ブロックより、不要なファイルを置かない、ソフトウェアを更新する、狙われやすいパスを Web サーバーの設定で一括して拒否する、といった根本的な対策を優先してください。fail2ban などで自動的に一時ブロックする仕組みは補助として有効です。

CVE-2024-4577 はLinuxのサーバーにも影響しますか?

この脆弱性は Windows の文字コード変換の仕組みが原因のため、影響を受けるのは Windows 上で PHP を CGI として動かしている環境です。Linux のサーバーは対象外ですが、Linux でもサポート切れの PHP は別の脆弱性が修正されないため、更新は必要です。