働く 2026-01-07

【緊急対応】問い合わせフォームの大量送信攻撃(スパム)を今すぐ止める方法と恒久対策【PHP実装付き】

「朝起きたら、問い合わせフォームから 1000 件以上の謎の英語メールが届いていた…」 「お客様から『資料請求できない』と連絡が入った…」

もし今、あなたがこの状況に直面しているなら、それはフォーム大量送信攻撃(Form Spamming / Form Bombing)の被害に遭っています。

放置すると、単にメールボックスが汚れるだけでなく、会社のドメインがブラックリストに登録され、重要なお客様へのメールすら届かなくなるという最悪の事態を招きます。

この記事では、実際に企業のフォーム攻撃被害に対応した経験をもとに、「今すぐやるべき緊急対応」「二度と被害に遭わないための恒久的な技術対策(PHP 実装コード付き)」、そして「顧客への報告メールテンプレート」までを網羅的に解説します。

フォーム攻撃のイメージ

なぜ「スパムメール」は危険なのか?

「迷惑メールフォルダに入るから無視すればいい」と考えてはいけません。フォーム攻撃には、業務妨害以上の明確な悪意とリスクがあります。

  1. ドメイン評価の毀損(ブラックリスト入り)
    • あなたのサーバーから大量の自動返信メールがばら撒かれることで、Gmail や Microsoft などのメールプロバイダから「このドメインはスパム送信元だ」と判定されます。
    • 結果、お客様への見積もりメールや採用通知などが「迷惑メール」扱いされ、届かなくなります。
  2. 踏み台としての悪用
    • 攻撃者は、フォームの自動返信機能を利用して、第三者にフィッシング詐欺サイトへのリンクなどを送りつけます。あなたの会社が「詐欺メールの加害者」に見えてしまうのです。
  3. サーバーリソースの枯渇
    • 短時間に数千〜数万件のリクエストが飛び交うことで、サーバーがダウンし、Web サイト全体が閲覧不可になる可能性があります。

【フェーズ 1】今すぐやるべき緊急対応

攻撃が現在進行形で続いている場合、まずは出血を止めることが最優先です。技術的な対策を実装する時間稼ぎのために、物理的にフォームを止めましょう。

方法:フォームをメンテナンス中にする

PHP でフォームを実装している場合、変数を 1 つ挟むだけで一時停止できます。

<?php
// 緊急対応: フォームを一時停止する場合は true にする
$form_disabled = true;
?>

<!-- HTML部分 -->
<?php if (!$form_disabled) { ?>
    <!-- 既存のフォームコード -->
    <form action="..." method="post">
        ...
    </form>
<?php } else { ?>
    <!-- メンテナンス表示 -->
    <div class="alert alert-warning" style="padding: 20px; background: #fff3cd; border: 1px solid #ffeeba; border-radius: 4px;">
        <h3 style="margin-top:0;">資料請求フォームは現在メンテナンス中です</h3>
        <p>システム調整のため、一時的にフォームを停止しております。<br>
        お急ぎの方は、お電話にてお問い合わせください。<br>
        <strong>TEL: 03-xxxx-xxxx</strong></p>
    </div>
<?php } ?>

これで攻撃は物理的に止まります。この間に、落ち着いて以下の「恒久対策」を実装してください。


【フェーズ 2】絶対に突破させない「4 層の防御壁」を作る

ボットの攻撃手法は年々高度化しています。「reCAPTCHA さえ入れれば安心」という時代ではありません。以下の 4 つの対策を組み合わせることで、利便性を損なわずに鉄壁の防御を構築します。

セキュリティ対策の全体像

対策 1:ハニーポット(Honey Pot)

効果:★☆☆☆☆(単純なボットに有効) 副作用:なし

人間には見えない「隠し入力欄」を作り、そこに入力があったら「ボット」とみなして弾く手法です。人間は隠しフィールドが見えないので入力しませんが、HTML だけを解析するボットはすべてのフィールドを埋めようとします。

実装コード(HTML):

<!-- CSSで画面外に追いやる -->
<div style="position: absolute; left: -9999px;">
  <!-- name属性は 'website' や 'url' など、ボットが食いつきそうな名前にする -->
  <input
    type="text"
    name="spam_check"
    value=""
    tabindex="-1"
    autocomplete="off"
  />
</div>

実装コード(PHP/受信側):

// ハニーポット検証
if (!empty($_POST['spam_check'])) {
    // ボットと判定。エラーは出さず、送信成功したフリをして終了させる(die)のがベスト
    // 相手に「対策された」と悟らせないため
    die();
}

対策 2:セッションベースの送信頻度制限(Rate Limit)

効果:★★★☆☆(連続投稿に有効) 副作用:正規ユーザーが連打した(ダブルクリック)際にエラーになる可能性

「1 時間に 3 回まで」といった制限を設けることで、短時間の大量送信を防ぎます。

session_start();

function checkRateLimit() {
    $now = time();
    $limit_time = 3600; // 制限時間(1時間)
    $max_attempts = 3;  // 最大送信回数

    if (!isset($_SESSION['form_submissions'])) {
        $_SESSION['form_submissions'] = array();
    }

    // 古い記録を削除(1時間以上前のタイムスタンプを除外)
    $_SESSION['form_submissions'] = array_filter(
        $_SESSION['form_submissions'],
        function($timestamp) use ($now, $limit_time) {
            return ($now - $timestamp) < $limit_time;
        }
    );

    // 制限チェック
    if (count($_SESSION['form_submissions']) >= $max_attempts) {
        return false;
    }
    return true;
}

// 送信成功時に記録する関数
function recordSubmission() {
    $_SESSION['form_submissions'][] = time();
}

対策 3:Google reCAPTCHA v3(最強の盾)

効果:★★★★★(高度なボットも検知) 副作用:導入の手間が少しある

現在、最もスタンダードかつ強力な対策です。v2(「私はロボットではありません」のチェックボックス)とは異なり、v3 はユーザーに何もさせずにバックグラウンドでスコア判定を行います。

1. 鍵の取得 Google reCAPTCHA Admin Console から、v3 のサイトキーとシークレットキーを取得してください。

2. HTML 側(送信トークンの取得)

<script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY"></script>
<script>
  document.querySelector("form").addEventListener("submit", function (e) {
    e.preventDefault();
    grecaptcha.ready(function () {
      grecaptcha
        .execute("YOUR_SITE_KEY", { action: "submit" })
        .then(function (token) {
          // トークンを隠しフィールドにセットして送信
          var input = document.createElement("input");
          input.type = "hidden";
          input.name = "recaptcha_token";
          input.value = token;
          e.target.appendChild(input);
          e.target.submit();
        });
    });
  });
</script>

3. PHP 側(スコア検証)

function verifyRecaptcha($token) {
    $secret = 'YOUR_SECRET_KEY';
    $response = file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret={$secret}&response={$token}");
    $result = json_decode($response);

    // スコア0.5以上を人間とみなす(サイトによって調整)
    return $result->success && $result->score >= 0.5;
}

if (!verifyRecaptcha($_POST['recaptcha_token'])) {
    // ボット判定時の処理
    $error['recaptcha'] = "不正なアクセスと判定されました。";
}

対策 4:CSRF トークン

効果:★★☆☆☆(外部サイトからの強制送信防止)

自分のサイトのフォームを経由せずに、外部から直接プログラムで POST 送信してくる攻撃を防ぎます。

// トークン生成(フォーム表示時)
if (empty($_SESSION['csrf_token'])) {
    $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}

// トークン検証(受信時)
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
    die("不正なリクエストです");
}

【フェーズ 3】顧客・社内への報告メールテンプレート

技術的な対応が終わっても、仕事は終わりではありません。上司やクライアントへの報告までがセットです。状況に合わせて使えるテンプレートを用意しました。

パターン A:緊急対応完了(とりあえず止めた)報告

とにかく急いで「対応しました」と伝えるためのメールです。

件名:Re: 【対応完了】資料請求フォームの一時停止措置について

〇〇様

お疲れ様です。××です。
ご連絡いただいたフォームへの大量送信攻撃の件、急ぎ対応いたしました。

【対応内容】
以下のフォームを一時停止(アクセス不可)とし、「現在メンテナンス中」のメッセージと電話窓口の案内を表示しております。

・資料請求フォーム:https://...
・お問い合わせフォーム:https://...

これにより、これ以上のスパム送信は物理的に停止しております。

今後の対応として、本日中に「Google reCAPTCHA」を含むセキュリティ対策の実装を行い、
安全が確認でき次第、フォームを順次再開する予定です。

取り急ぎご報告まで。
よろしくお願いいたします。

パターン B:恒久対策完了&再開の報告

対策が済み、フォームを再開する際のメールです。

件名:Re: 資料請求フォームのセキュリティ対策完了と再開のご報告

〇〇様

お疲れ様です。××です。

停止しておりました資料請求フォームにつきまして、
以下のセキュリティ強化対策の実装が完了いたしました。

1. Google reCAPTCHA v3(AIによる自動ボット判定)の導入
2. 送信頻度制限機能(短時間の連続送信をブロック)
3. ハニーポット(スパム用隠しフィールド)の設置

テスト送信にて正常に動作することを確認いたしましたので、
先ほどフォームを再開(公開)いたしました。

現在は正常にお問い合わせいただける状態ですので、ご安心ください。
今回の対策により、従来のスパム攻撃の99%以上は遮断できる見込みです。

ご迷惑をおかけいたしましたが、よろしくお願いいたします。

まとめ:攻撃者は「隙」を探している

フォームのスパム攻撃は、家の鍵が開いていれば泥棒が入るのと同じで、対策していないフォームが見つかれば必ず狙われます。

  1. まずハニーポットCSRF トークンを入れる(最低限のマナー)。
  2. できればreCAPTCHA v3を入れる(今のスタンダード)。
  3. 攻撃が来たら、焦らずフォームを一時停止する。

IT 担当者として、この「守りの手札」を持っているだけで、夜も安心して眠れるようになります。まずは今日、ご自身の管理サイトの対策状況をチェックしてみてください。