Phishingでパスワードが盗まれた後 ― Web層でCredential Stuffingを止める
フィッシングで盗まれたパスワードは、数ヶ月後にログインページへ再投入されます。WAFのrate limitingで止められる範囲を整理します。
フィッシングでパスワードが盗まれた後 ― Web層でCredential Stuffingを止める
ある社員が偽メールのリンクを開き、会社のログイン画面とそっくりなページにメールアドレスとパスワードを入力してしまいます。情報システム部門は数時間以内に気づき、そのアカウントのパスワードをリセットし、全社に注意喚起を出して、対応を終えます。
その3ヶ月後、自社のECサイトで1日あたり数千件のログイン失敗が記録され始めます。
盗まれたパスワードは、リセットした時点で役目を終えたわけではありません。転送され、売買され、combo listにまとめられ、同じ人物が使っていそうな他のサイトに片端から試されます。この工程がcredential stuffingであり、舞台は社員の受信箱ではなく、あなたのログインページです。
漏れたパスワードが自社サイトに戻ってくる理由
多くの人はパスワードを使い回します。credential stuffingが攻撃者にとって割に合うのは、この一点があるからです。サイトAから漏れたパスワードがサイトBでも通る確率がごくわずかであっても、数十万件を投げれば手元にアカウントが残ります。
フィッシングで漏れた1組のパスワードがたどる典型的な経路はこうです。

重要なのは、漏洩から実際に使われるまでに数ヶ月から数年の開きがあることです。インシデント発生時のパスワードリセットが効くのは、自社が管理しているアカウントだけです。その社員が同じパスワードを使い回している他のサイトまでリセットして回る人はいません。そして逆方向も同時に起きています。他所でフィッシングに遭った自社の顧客が、すでに漏れたパスワードを持ってログインしに来ているわけです。
自社の情報がそうした売買の場にすでに出回っているかどうかを知りたい場合、それはdark web monitoringの領分で、本記事とは別の関門です。ここで扱うのは「すでに漏れていて、いま撃ち返されている。Web層でどう受けるか」という段階です。フィッシング被害が判明した直後の対応手順はフィッシング対応playbookにまとめてあります。
Credential stuffingは「攻撃」の顔をしていない
多くのツールがこれを取り逃がすのは、そのためです。
credential stuffingのリクエストは、/login宛のHTTP POSTで、書式として正しいメールアドレスと、書式として正しいパスワードが載っています。SQLインジェクションもなければ、不審なペイロードもなく、シグネチャが引っかかる材料が何もありません。完全に正常なログイン要求で、ただパスワードが違うだけです。
しかも本業でやっている相手は、単一のIPから連射したりしません。多数のプロキシに分散し、ゆっくり投げ、ユーザーエージェントを入れ替え、時間帯もずらします。1つのIPだけを見れば、パスワードを2、3回打ち間違えた普通の利用者にしか見えません。
リクエストを1件ずつ見ても何も出てきません。異常が現れるのは全体像のほうです。ログイン成功と失敗の比率が普段の形から崩れている、1つのIPから重複のないメールアドレスが何十件も来ている、サイト全体のトラフィックは平常なのに特定のエンドポイントだけ401が跳ね上がっている、といった具合です。ここがWAFの見られる層で、アプリケーションに届く前にログインのリクエストをすべて通す位置にいるからです(WAFで何ができるのかがまだ曖昧なら、先にWAFとはをどうぞ)。
実際の画面ではどう見えるか
zcrWAFのRate Limiting画面(Rulesメニュー配下で、Custom Rules・Alert Rules・IP Groupsのタブと並んでいます)には、この話に直接関わるスイッチが2つあり、デモではどちらも有効になっています。
Visit Limit。 画面上の説明は "Limit requests from a single IP within a time window to prevent high frequency access." です。デモの設定値はTrigger Thresholdが1200 REQ、Block Durationが300 SEC。
ここはラベルを正確に読む必要があります。300秒はブロックを継続する時間であって、1,200件を数える時間ウィンドウの長さではありません。ウィンドウのほうはShow Advanced Optionsの内側にある別の値で、デモでは開かれていません。つまりこの画面からは、1,200件がどれくらいの時間で数えられるのか分からないということです。毎秒何件に相当するかも計算できません。
Attack Limit。 "Limit attacks from a single IP within a time window to prevent repeat attacks." こちらははるかに厳しく、20 REQで900 SEC(15分)のブロックです。
この2つを、先ほどのcredential stuffingの挙動に重ねてみます。
- どちらも説明文のとおり「単一のIPから」を数えます。ここが要点です。ウィンドウの長さが分からなくても、1つのIPあたり1,200件というのはログインフォームで踏むには高すぎるハードルですし、数十のIPに分散して投げるボットなら、どのIPもその数字に近づきません。ウィンドウが何秒であっても結論は変わりません。
- Attack Limitのほうも説明文のとおり、システムがすでに攻撃と判定したものを数えます。ところが書式の正しいメールアドレスと書式の正しいパスワードが載ったログインPOSTは、そもそも攻撃のパターンに当てはまりません。20件という枠に入る見込みは薄いでしょう。
要するにこの2つのスイッチは、狙って作られた対象 ― 単一IPからの高頻度な連射と、判定済みの攻撃の反復 ― に真っ直ぐ向いています。そして腰を据えたcredential stuffingは、そのどちらの条件も満たさないように組み立てられています。
この画面がもう一つ教えてくれるのは、エンドポイントを指定する欄がどこにもないことです。ここの値はサイト全体にかかるもので、/loginだけを対象にしたものではありません。ログインページだけ他より厳しくしたいなら、次に見るべきは隣のCustom RulesとIP Groupsのタブ、そして黙ってブロックされるより信号がほしい場合はAlert Rulesということになります。
もう一点、画面上部にサイトの切り替えがあります。設定がサイト単位で分かれているということで、これは理にかなっています。顧客のログイン画面を抱えるサイトと、誰もログインしない会社案内サイトとで、同じ厳しさを使う理由はないからです。
rate limitingの仕組み全体と、実利用者を巻き込まずに設定する方法はWAFでBotとLayer 7 DDoSを防ぐに別記事として書きました。本記事は、パスワードが漏れた後の再投入というケースだけに絞っています。
正直なところ、WAFは何を止めて何を止められないのか
| 状況 | WAFがどこまで効くか |
|---|
| 単一IPからのパスワード連射 | Visit Limitの担当範囲です。ただし実際に発動するかは、Advanced Optionsに隠れている集計ウィンドウ次第です。Attack Limitのほうは、速く投げようが書式の正しいログインPOSTである以上、やはり数えません |
| プロキシ経由で多数のIPに分散した低速な試行 | IP単位の上限では捕まりません。ログインエンドポイントに紐づけたルールが要ります。また「見えるかどうか」はログやレポート側の話で、この設定画面の話ではありません |
| 投げられたパスワードが実際に正しかった場合 | 止められません。 WAFから見れば通常のログイン成功です |
| 同じアカウントが数分差で別々の国からログイン成功 | WAFの範囲外です。ログ/SIEMか認証基盤側で見る必要があります |
最後の行ははっきり言っておく価値があります。rate limitingは、盗まれたパスワードを使えなくするものではありません。 推測に時間がかかるようにし、必要なIPを増やし、コストを上げ、痕跡を残させる。それだけです。認証の層で問題そのものを断つのはMFAであり、zcrWAFはMFAを提供しません。そこは現在お使いの認証システムの担当です。WAF1つでcredential stuffingが片付くと言う相手は、売り込みが過ぎます。
正しい捉え方は、2つの関門を組み合わせることです。MFAが正しいパスワードの価値をほぼ消し、WAFが「当たるまで試し続ける」工程の採算を合わなくする。そして、まだ試している最中に気づけるようにする。
この話が自社に当てはまるサイン
- サイト全体のトラフィックは変わっていないのに、ログイン失敗(401/403)が波状に跳ね上がる
- 普段の顧客層が使うとは考えにくい国や時間帯からのログイン成功がある
- 直近でフィッシング被害があり、当該アカウントだけリセットして、同じパスワードを使っていた他のアカウントの変更までは求めていない
- 顧客向けログイン画面にMFAがなく、アカウント単位の入力失敗回数の制限もない
- 「先月のログイン失敗は何件でしたか」に答えられない。誰もその数字を見ていないため
最後の項目が最も多く、そして最も直しやすい項目です。データはすでにシステムの中にあり、信号を出す設定が誰にもされていないだけだからです。
zcrWAFはどこを担当するか
zcrWAFはアプリケーションの手前に置かれるため、ログインページに向かうリクエストをサイトに届く前にすべて見ています。Rules画面にはRate Limiting、Custom Rules、IP Groups、Alert Rulesの4つのタブがまとまっていて、サイト全体のデフォルトだけに頼らずログインページ専用のルールを組みたいときは、この一式を順に見ていくことになります。
zcrWAFがやらないのはMFAと本人確認で、そこは従来どおり認証基盤の担当のままです。運用中のサイトがどの関門から着手すべきか判断がつかない場合は、zcrWAFのプランをご覧ください。
お問い合わせ
運用中のサイトのログインページに、漏れたパスワードによるログイン試行がどれだけ来ているか気になりませんか。無料でご相談いただけますので、お気軽にお問い合わせください。
出典
- OWASP — Credential Stuffing — 本記事の説明と一致するcredential stuffingの定義。漏洩したusername/passwordの組を自動投入する攻撃で、パスワード使い回しの習慣に依存する
- OWASP — Credential Stuffing Prevention Cheat Sheet — MFAを主要な対策として位置づけており、本記事の結論(WAFは攻撃のコストを上げるが、identity層の問題を実際に塞ぐのはMFA)と一致