動かしていなかったから、漏れていなかっただけ

執筆者:

カテゴリ:

問い合わせフォームにボット対策を入れようとして、先に別のことが分かりました。

いまの作りでは、ブラウザ側にどんな対策を入れても効きません。

この記事で扱うこと

送信先のURLが配信されるJavaScriptに入る作りになっていた話と、その直し方です。あわせて、画像の文字を読ませる方式を選ばなかった理由も書きます。

先頭の6文字が、置き場所を決めていた

このサイトはNext.jsで作っています。環境変数の名前には、決まりがあります。

名前 どこから見えるか
CONTACT_ENDPOINT サーバーだけ
NEXT_PUBLIC_CONTACT_ENDPOINT ブラウザにも配られる

名前の先頭に NEXT_PUBLIC_ が付いていると、その値は組み立てのときにJavaScriptの中へ埋め込まれます。訪問者に配られるファイルの一部になる、ということです。

フォームはブラウザの中で動く部品なので、送信先を知る必要がありました。だから素直に NEXT_PUBLIC_ を付けていました。付けなければ読めないので、それ以外に選びようが無いように見えていました。

鍵の掛かっていない扉が、隣に並ぶ

この形だと、送信先のURLはフォームを開かなくても分かります。配られたファイルを開けば書いてあります。

フォームを通さずに送れる

見えない入力欄を足しても、送信までの時間を測っても、それらはフォームを使った場合にだけ効きます。

送信先を直接叩く相手には、そもそも通り道が違うので関係がありません。鍵を掛けた扉の横に、鍵の掛かっていない扉が並んでいる状態でした。

動かしていなかったから、漏れていなかった

ここで確認したところ、本番の環境変数は設定されていませんでした。

フォームは、送信先が無いときは「お問い合わせ先は準備中です」と出す作りにしてあります。つまり公開されてからずっと、フォームは表示されておらず、URLもどこにも出ていませんでした。

安全だったのではなく、使っていなかっただけ

結果として何も漏れていませんが、設定を入れた瞬間に漏れる形のまま置いてありました。

この種の問題は「まだ起きていない」と「起きない」の区別が付きにくく、動かし始めた日にまとめて効いてきます。

ついでに言うと、フォームが出ていなかったこと自体も問題でした。問い合わせ先として案内していた場所が、ずっと準備中だったということになります。

自分のサイトに窓口を作る

直し方は、間に1枚挟むことでした。

前 後
送信先 ブラウザ → 外部サービス ブラウザ → 自分のサイト → 外部サービス
URLの在り処 配られるJavaScript サーバーだけが持つ
判定の場所 ブラウザ(迂回できる) サーバー(迂回できない)

ブラウザから見えるのは /api/contact だけになります。ここを直接叩くことはできますが、叩いた先で何を見ているかは分かりません。

画像の文字を読ませる方式は、入れなかった

ボット対策というと、ゆがんだ文字や、信号機の写真を選ばせるものが思い浮かびます。今回は入れていません。

読みにくい文字は、機械より先に人が脱落する

問い合わせは、そもそも件数が多くありません。1日に何百件も来るものではない。

それに対して、1件取りこぼす損のほうが大きいと考えました。迷惑な送信を100件止める価値より、相談しようとした人が1人あきらめる損のほうが重い、という判断です。

人がやらないことを、3つ見る

代わりに置いたのは、訪問者の手間が一切増えない3つです。

見ること 人がやらない理由
見えない欄が埋まっている 画面に出ていないので、触りようがない
開いてすぐ送っている 3秒で文章は書けない
短時間に何度も送っている 同じ相談を10分に4回はしない

どれも、正しく使っている人には何も起きません。止めるために何かをさせるのではなく、やっていないことを確認する形にしています。

見えない欄の名前を、慎重に決めた

ひとつだけ、注意が必要な部分があります。見えない欄の名前です。

この欄を name や url のような一般的な名前にすると、ブラウザやパスワード管理ソフトの自動入力が、画面に出ていなくても勝手に埋めることがあります。

人の送信が、黙って捨てられる

この欄が埋まっている送信は、機械とみなして捨てます。しかも成功したように見せて捨てます。理由を返すと、次からその欄を避ければ通ると分かってしまうからです。

つまり自動入力に埋められた人は、送信したつもりで、何も届いていない状態になります。これがこの仕組みの一番の失敗です。

自動入力が狙わない名前にしたうえで、キーボードの移動先からも読み上げの対象からも外しています。

回数の数え方には、限界がある

正直に書いておくと、短時間の回数を数える部分は完全ではありません。

このサイトのサーバー側の処理は、必要なときに起動して、しばらくすると消えます。数えた記録は共有されず、消えるときに一緒に無くなります。厳密には数えられません。

それでも、続けて叩いてくる相手は同じ実体に当たりやすいので、一番困る「短時間に何百件」は止まります。正確さが要るようになったら、外に記録を置くことになります。いまの流量でそこまで持つ必要は無いと判断しました。

今回の学び

まず、名前の先頭6文字が、置き場所を決めていたということ。NEXT_PUBLIC_ は便利な省略ではなく、「これは配る」という宣言でした。付けなければ読めないから付ける、では順番が逆でした。

次に、ブラウザ側の判定は、通り道が1本のときにだけ効くこと。もう1本、鍵の掛からない道が並んでいれば、そちらが使われます。対策を足す前に、道が何本あるかを数える必要がありました。

そして、止めるために手間を増やさないこと。問い合わせのように件数が少ないものでは、止めた数より取りこぼした数のほうが重くなります。人がやらないことを確認するだけなら、正しく使う人には何も起きませんでした。

コメント

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です