フォームを実際に守るもの:CAPTCHA、ハニーポット、時間トラップ、CSRF
多くのお問い合わせフォームは、一つの仕掛けだけにスパム対策を頼っています。その多くは最も単純なボットしか止めません。各保護層が何を止め、何を負担にし、どの組み合わせが適切かを説明します。
お問い合わせフォームのスパムは、人が手入力していることはほとんどありません。大半は、フォームを見つけ、すべての欄に入力し、その結果を何千回も送るソフトウェアです。対策はいくつかあり、それぞれが大きく異なる段階で働きます。各対策が実際に何をするかを知ることで、本当の保護がないフォームと、厳重に守りすぎて本物の利用者が諦めるフォームという、二つの失敗を避けられます。
- ハニーポット:すべての欄に入力する単純なボット
- 時間トラップ:読み込み直後に送信するスクリプト
- CAPTCHA:一般的な自動化の大半
- CSRF トークン:エンドポイントへ直接送られるリクエスト
- レート制限:一つの送信元からの大量送信
- プルーフ・オブ・ワーク:追跡やパズルを使わず、低コストな大量送信を防ぐ
- サーバー側のチェック:ブラウザーを迂回するすべての送信
- 標的型ボットは飛ばす。隠し方が悪いとスクリーンリーダーが読み上げる
- 待機するボットは通る。サーバー側の署名がなければ簡単に偽造できる
- すべての人への負担、アクセシビリティ上の障壁、多くは第三者の利用。解読代行サービスも存在する
- 最初にページを読み込むボットも有効なトークンを取得する
- 多数の IP アドレスに分散したスパム
- 計算能力のある執拗な送信者は防げない。JavaScript が必要
- 単独ですべては防げない。しかし、これがなければ他のすべての層は飾りにすぎない
ハニーポットと時間トラップ:見えないフィルター
ハニーポットは、人には見えない追加の入力欄です。例えば「website」という名前の欄を CSS で隠します。単純なボットはすべての欄に入力するため、ハニーポットに値があれば自動処理と判断でき、サーバーは静かにメッセージを破棄できます。そのサイト向けに作られたボットや、ブラウザーと同様にページを描画するボットは飛ばします。正しく隠すことが大切です。画面外へ移動しただけの欄は、スクリーンリーダーが読み上げたり、Tab キーで到達できたり、自動入力で埋まったりします。aria-hidden、tabindex -1、autocomplete off を使い、そこに到達した人に空欄のままにするよう求める中立的なラベルも付けてください。
時間トラップはフォームを配信した時刻を記録し、不自然に速く届く送信を拒否します。人は読んで入力するのに数秒必要ですが、多くのスクリプトは一秒未満で送信します。タイムスタンプはサーバーで確認し、署名やセッション内の保持などによって改ざんから守る必要があります。単純な隠し時刻欄は、ボットが書き換えるだけです。自動入力で本物の利用者も速くなるため、しきい値は低く保ってください。単に待つボットは通過します。時間トラップはフィルターであり、壁ではありません。
CAPTCHA:有効ですが、負担もあります
CAPTCHA は、画像パズルからバックグラウンドのチェックまで、ボットが操作していない証拠を求めます。代表的なサービスには reCAPTCHA、hCaptcha、Cloudflare Turnstile、Friendly Captcha があります。一般的な自動化の大半を止めるため、広く使われています。しかし、目に見えるパズルはどれも、一部の訪問者が諦める障壁になります。また、多くのサービスは第三者のスクリプトを読み込み、プライバシーや同意の問題を生じさせます。CAPTCHA が役立つのは、正しく設定した場合だけです。公開テスト用サイトキー、スクリプトのないウィジェット、サーバーが検証しないトークンは、保護に見えても保護ではありません。formexposed.com の無料チェックは、このような誤りを外側から指摘します。
アクセシビリティも、その負担の一部です。画像パズルは全盲の人や多くの弱視の人を排除し、音声の代替手段は盲ろうの人を助けません。難しい論理問題は、認知障害のある人に負担をかけます。WCAG 2.2 の達成基準 1.1.1 は、CAPTCHA の目的を説明するテキストの代替と、異なる感覚に対応する代替形式を求めます。バックグラウンドのチェックは大半を避けられますが、不審と判断した場合の代替手段が、再び画像パズルになることもよくあります。その経路をキーボードとスクリーンリーダーでテストしてください。
CSRF トークン:偽造への対策であり、スパム対策ではありません
CSRF トークンは、サーバーがフォームに埋め込み、返送を求めるランダムな値です。他のサイトが訪問者の意図しないリクエストをそのブラウザーから送らせる、クロスサイトリクエストフォージェリへの対策として設計されました。公開のお問い合わせフォームでは、副次的な効果があります。ページを読み込まず、フォームのアドレスに直接送るボットを拒否できます。ページを取得し、トークンを返すボットはすべて通過します。ほとんどのフレームワークやフォームプラグインには、もともと CSRF トークンがあります。有効にしておくべきですが、スパム対策として数えないでください。
サーバーで行うべきこと
- すべての欄をサーバーで再検証します。必須項目、長さ、メール形式を確認し、メールヘッダーに入る欄には改行を認めないようにします。
- 送信のたびに CAPTCHA とプルーフ・オブ・ワークのトークンを、発行元サービスまたは自分のコードで検証し、再利用されたトークンを拒否します。
- IP アドレスと時間枠ごとに送信回数を制限します。一つの送信元からの大量送信は止まりますが、多数のアドレスに分散したスパムには他の層が必要です。
- プルーフ・オブ・ワークも検討してください。送信前にブラウザーが小さな計算課題を解きます。訪問者にパズルを見せず、追跡もしませんが、大量送信のコストは上がります。
適切な組み合わせ:二、三の層
- 1見えない層から始めます。アクセシビリティに配慮したハニーポットと、署名付きの時間トラップを、どちらもサーバーで確認します。
- 2IP アドレスごとのレート制限を追加し、一つの送信元からフォームに大量送信できないようにします。
- 3標的型のスパムがまだ通る場合、プルーフ・オブ・ワークまたは CAPTCHA を追加します。できれば目に見えるパズルがなく、アクセシブルな代替手段があるものを選びます。
- 4フレームワークが提供する CSRF トークンは維持します。ただし、防御ではなく付加的な効果として考えます。
- 5訪問者の立場で、キーボードのみ、スクリーンリーダー、携帯電話を使って結果をテストし、本物のメッセージが届くことも確認します。
多くのサイトでは、ハニーポット、時間トラップ、レート制限を組み合わせるだけで、目に見える障壁なしに一般的なスパムの大半を除去できます。CAPTCHA は、それでは足りない場合の予備です。WordPress 向けの無料 formexposed プラグインは、Google を必要とせず、ハニーポット、時間チェック、プルーフ・オブ・ワークを組み合わせます。外側からフォームがどう見えるか、どの層が存在し、CAPTCHA が有効に設定されているかは、formexposed.com の無料チェックで確認できます。必要なのはドメインだけで、アカウントは不要です。サーバーのコードは見えないため、サーバー側の部分はご自身で確認する必要があります。