お問い合わせフォームのスパムを止める

お問い合わせフォームのスパムを止める1 分で読めます

ボットだけが埋めて人は埋めないハニーポットフィールドを追加する方法

スクリーンリーダー、キーボード、自動入力の邪魔をせずにボットを捕まえるハニーポットを、各スタックのサーバー側チェックとあわせてどんなフォームにも追加します。

Preet SutharIkiform 創業者

テキスト入力欄を 1 つ追加し、画面外に隠して Tab 順から外し、aria-hidden で包み、どのブラウザーも自動入力しない名前を付けます。人は決して入力しませんが、すべての入力欄を埋めるボットは入力します。サーバーでは値が入った送信をすべてスパムとして扱い、本物のメッセージとまったく同じように応答します。

ハニーポットならではの点

ハニーポットは 2 つの顔を同時に持つ必要があります。HTML を読むボットには、埋める価値のある普通のフィールドに見えなければなりません。そしてすべての人にとっては、存在しないものでなければなりません。それには、あなたとは違う方法でフォームを使う人も含まれます。スクリーンリーダーを使う人、キーボードで Tab 移動する人、パスワードマネージャーにフォームを埋めてもらう人です。ハニーポットの不具合のほとんどはこうした人の誰かを忘れることから起き、その症状は本物のメッセージが黙ってスパムに振り分けられることです。

人とボットが同じハニーポットフィールドに出会うとき人(どのブラウザーや支援技術でも)スクリプトのボットフォームに入力画面、キーボード、スクリーンリーダー罠を素通り画面外、tabindex-1、aria-hidden自動入力が無視ブラウザーが知らない名前受け付け罠は空HTML を解析すべての入力欄を発見すべてを埋める罠も含めてすぐに送信スパム同じ成功の応答人とボットが同じハニーポットフィールドに出会うとき人(どのブラウザーや支援技術でも)スクリプトのボットフォームに入力画面、キーボード、スクリーンリーダー罠を素通り画面外、tabindex -1、aria-hidden自動入力が無視ブラウザーが知らない名前受け付け罠は空HTML を解析すべての入力欄を発見すべてを埋める罠も含めてすぐに送信スパム同じ成功の応答
  1. 人は画面、キーボード、スクリーンリーダーなど、自分の使う手段でフォームに入力します。
  2. 罠は画面外にあり、Tab 順から外れ、支援技術からも隠れているので、人がそこに行き着くことはありません。
  3. ブラウザーやパスワードマネージャーが自動入力しない名前なので、空のままです。
  4. 送信は空の罠を持って届き、受け付けられます。
  5. スクリプトのボットは HTML を解析し、罠を含むすべての入力欄を見つけます。
  6. すべてを埋めて、すぐに送信します。
  7. 罠に値があるので、その送信はスパムです。それでもボットには普通の成功の応答が返ります。
上の段の安全策は、本物の人がフィールドに行き着く経路をそれぞれ 1 つずつふさいでいます。どれか 1 つでも外すと、上の段もスパムで終わりかねません。

マークアップ

罠はフォームの中、本物のフィールドの隣に、普通のテキスト入力欄として置きます。type="hidden" の入力欄では機能しません。人が編集できないものだとボットは知っていて、手を付けないからです。

contact.html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="POST">
  <label for="email">Email</label>
  <input id="email" name="email" type="email" autocomplete="email" required />
  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>

  <div class="hp" aria-hidden="true">
    <label for="hp-field">Leave this empty</label>
    <input id="hp-field" name="_gotcha" type="text" tabindex="-1" autocomplete="off" />
  </div>

  <button>Send</button>
</form>
スタイル
<style>
.hp {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
</style>
  • ラッパーに aria-hidden="true" を付けると、ラベルと入力欄がアクセシビリティツリーから外れ、スクリーンリーダーが読み上げなくなります。
  • tabindex="-1" で、誰にも見えない入力欄に Tab キーで止まらないようにします。
  • ラベルには Leave this empty(空のままにしてください)と書きます。何かのツールがフィールドを見せてしまっても、読んだ人は何をすべきかわかります。
  • required は付けないでください。人に見えない必須フィールドは、誠実な送信をすべて妨げます。

隠し方

ボットは、明らかに隠されたフィールドを飛ばすことを覚えました。単純なスクレイパーはいまだにすべてを埋めますが、入力前に hidden 属性やインラインの display: none を確認するものもあります。隠し方が入力欄そのものから遠いほど、多くのボットが引っかかります。

手法人から隠れるかまだ捕まえられるボット
hidden 属性かインラインの display: noneはい最も単純なものだけ。賢いボットが最初に確認する点
スタイルシートの画面外クラスはいほとんど。見分けるには、ボットが CSS を読み込んで適用する必要がある
opacity: 0 やサイズ 0ほぼ隠れる。拡大鏡やフォーカスの枠で見えてしまうことがあるほとんど。ただし人にとってのリスクは高め
読み込み後に JavaScript で追加はいスクリプトを実行するボット。素の HTML スクレイパーには見えないので、それらは逃す

スタイルシートの画面外クラスを使ってください。最も多くのボットを捕まえ、人にとっても最も安全です。ハニーポットが効かなくなったら、もっと巧妙な隠し方を考えるより、別の名前で 2 つ目を追加してください。

自動入力が無視する名前を選ぶ

ブラウザーやパスワードマネージャーは、name、id、ラベル、autocomplete の値から推測してフィールドを埋めます。autocomplete="off" はヒントにすぎず、住所や連絡先に見えるフィールドでは無視するブラウザーもあります。だから実際に効くのは名前です。

避ける名前理由代わりに使う名前
email2, phone, name, address自動入力が認識し、本物の人の入力欄を埋めてしまう_gotcha, company_website
honeypot, trap, bot見え見えの名前のフィールドを飛ばすボットがいる地味でありそうな名前
url や website 単独保存したプロフィールから Web サイトのフィールドを埋める自動入力ツールがあるcompany_website のような複合語の名前

サーバーで確認する

ハニーポットは、サーバーが読んで初めて機能します。ボットはスクリプトを実行しないので、ブラウザー側のチェックは無意味です。フィールドに値があるときは、本物のメッセージとまったく同じように応答し、送信を保存も転送もしないでください。違う応答を返すと、どのフィールドでばれたのかをボットに教えてしまいます。以下の例では自前の saveMessage を呼んでいます。メッセージを保存したりメールしたりする処理に置き換えてください。

プレーンな HTML フォームには自前のサーバーがありません。送信先を Ikiform にして罠を _gotcha と名付けるか、フォームごとに Honeypot field で名前を変えてください。サーバー側のチェックは Ikiform が行い、罠が回答として保存されることはありません。

contact.html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="POST">
  <label for="email">Email</label>
  <input id="email" name="email" type="email" autocomplete="email" required />
  <label for="message">Message</label>
  <textarea id="message" name="message" required></textarea>

  <div class="hp" aria-hidden="true">
    <label for="hp-field">Leave this empty</label>
    <input id="hp-field" name="_gotcha" type="text" tabindex="-1" autocomplete="off" />
  </div>

  <button>Send</button>
</form>
罠にかかった送信は、保存しなくてもログに残してください。1 日あたりの件数を見れば、ハニーポットがまだ役に立っているかがわかり、急にゼロになったらボットが飛ばすことを覚えたということです。

Ikiform でのハニーポットの扱い

Ikiform のフォームには、デフォルトで _gotcha という名前のハニーポットがあります。フォームの設定の Honeypot field でフォームごとに変更でき、選んだ名前は予約され、回答として保存されることはありません。ハニーポットが埋められるとスパムスコアに 5 が加算され、それだけでしきい値の 5 に達します。

Ikiform は送信を捨てません。スパムとして残すので、本物の人が罠にかかってしまっても、メッセージを見つけて復元できます。スパムと判定された送信にも本物と同じ成功の応答を返すので、ボットは何も学べません。ステータス spam で保存され、通知メールも Webhook も送らず、使用量にもカウントされず、30 日後に削除されます。スパムをブロックしたワークスペースには毎週月曜日に、合計、最も多かったフォーム、主な理由をまとめたメールが 1 通届きます。リファレンスはスパムのドキュメントと HTML フォームにあります。

動作を確認する

  1. スクリーンリーダーをオンにしてフォームを読み込み、順に移動します。罠が読み上げられることはありません。
  2. Tab キーでフォームを移動します。フォーカスは最後の本物のフィールドからボタンに直接移ります。
  3. ブラウザーとパスワードマネージャーにフォームを自動入力させます。罠は空のままです。
  4. ハニーポットを _gotcha=bot と埋めて送信します。成功の応答は返りますが、送信データはスパムとして保存され、メールも Webhook も送られません。
  5. 普通のメッセージを送ります。受け付けられて届き、罠のフィールドの痕跡はありません。

ハマりどころ

  • JSON の送信。 FormData を使わずにボディを手で組み立てる場合は罠も含めてください。含めないと、サーバーはボットの場合も空として読みます。
  • フィールド名を変えるフォームビルダー。 入力欄に接頭辞を付けたり名前を変えたりするビルダーがあります。罠の本当の名前は、エディターではなく実際に送信されたボディで確認してください。
  • キャッシュ。 名前を変えた後もキャッシュされたページに古い罠の名前が残っていると、古い名前で送信が届いて通過してしまいます。両側で同時に名前を変えてください。
  • チェックボックスのハニーポット。 非表示のチェックボックスでも機能しますが、スクリーンリーダーは余計なチェックボックスをテキスト入力より上手に扱えません。テキスト入力欄を選んでください。
  • 層の 1 つ。 本物のブラウザーを動かして見えないフィールドを飛ばすボットは、どんなハニーポットも素通りします。レート制限と、必要なら人間確認 を組み合わせてください。

よくある質問

手順で詰まったときや、あなたの状況に合うガイドがほしいときはメールでどうぞ: hello@ikiform.com