本記事は2021/12時点の確認結果を元に記載しています。進化の早いクラウドサービスに関連する情報ですので、仕様は随時変化していく可能性がある点にご注意ください。また、セキュリティに関する機能ということもありますので、公開されている以上の内容には踏み込みません。
クラウドフレアのWAFにCloudflare Leaked Credentials Check(※)というルールセットがいつの間にやらリリース(GA)されたみたいです。本機能について日本語で書かれた記事が無さそう(2021/12時点)だったので、早速ですがこの機能を触ってみたメモを書いてみます!
※クラウドフレアのコンソール上ではCloudflare Leaked Credentials Checkと書かれていますが、開発者向けドキュメントには**Automated exposed credentials check**という名称で記載されています。
なお、本機能はFreeプランのアカウントでは利用できない点と、2021/3頃よりリリースされた新しいバージョンのWAFでのみ利用できる点にお気を付けください。
This feature is available to all paid plans.
Automated exposed credentials check
The Exposed Credentials Check Managed Ruleset is only available in the Cloudflare WAF announced on March 2021.
Configure exposed credentials checks in the dashboard
クラウドフレアのWAFは主に「Cloudflareマネージドルール」「OWASPルール」の2つのルールセットで構成されていて、ここに新たに本機能が追加されたようなイメージとなるのですが、クラウドフレアのWAF機能については以下記事が参考になりますので、本記事では触れないことにします。
https://www.mbsd.jp/research/20210329/cloudflare-waf-1/
https://www.mbsd.jp/research/20210405/cloudflare-waf-2/
https://www.mbsd.jp/research/20210412/cloudflare-waf-3/
機能の概要
本機能は漏洩した認証情報にマッチしたログイン試行を検知するためのルールセットとして提供されています。
↓Firewall -> WAF の画面に Cloudflare Leaked Credentials Check ルールセットがある
WAFに本ルールセットを追加して、ルールセットの中を覗いてみると、Wordpressなどの有名CMS製品のログイン画面や一般的なログイン画面(login.phpなど)などに対応したルールが設定されていることが分かります。保護対象アプリケーションが使用しているものに合わせて各ルールをOn/Offすると良いのかもしれません。
いずれかのルールにリクエストがマッチすると、リクエストヘッダにExposed-Credential-Checkヘッダが追加され、オリジンにリクエストが飛んでいきます。オリジンのアプリケーション側で Exposed-Credential-Check ヘッダの値に応じて、パスワードリセットだったり二要素認証を要求するなどして、リスト型攻撃などの対策として使ってねというという機能になっているようです。
Automated exposed credentials check#Available actions
↓イメージ図
検知テスト
検知確認用にApache httpdサーバを立てて、Exposed-Credential-Checkヘッダがロギングされるようにhttpd.confを設定してみました。
LogFormat "%h %l %u %t \"%r\" %>s %b %{Exposed-Credential-Check}i \"%{Referer}i\" \"%{User-Agent}i\"" cf_cred_check
CustomLog "logs/access_log" cf_cred_check
検知テスト用のパラメータが用意されているのでこれを使わせてもらいます。usernameをCF_EXPOSED_USERNAME、passwordをCF_EXPOSED_PASSWORDとしてリクエストしてみます。ここでは試しにJSONで投げてみました。
curl -X POST 'http://www.example.com/login.php' -H "Content-Type: application/json" -d '{"username":"CF_EXPOSED_USERNAME", "password":"CF_EXPOSED_PASSWORD"}'
分かりにくいですが、確かにExposed-Credential-Checkヘッダの値が1となりました。
192.0.2.1 - - [07/Dec/2021:02:20:35 +0000] "POST /login.php HTTP/1.1" 404 196 1 "-" "curl/7.68.0"
また、クラウドフレアのコンソールでログを見ると、リライト (=Exposed-Credential-Checkヘッダの追記) というアクションが実行されたことが分かります。しっかりとWAFのログとしてロギングされるため、アプリケーション側で追加の認証アクションを要求するような実装の対応ができなくとも、WAFのログをSIEMなどに取り込んで、アラートとして検出するという使い方もできそうです。
↓コンソールでログを確認
ここまで読むと、リクエストに予めExposed-Credential-Checkヘッダを空値などにして、WAFによるチェックを迂回したり、チェック結果をオリジンに誤解させることができそうかなと思ってしまうのですが、大丈夫です、Exposed-Credential-Checkヘッダのあるリクエストをブロックするルールがしっかりと存在していました!
curl -X POST 'http://www.example.com/login.php' -H "Content-Type: application/json" -H 'Exposed-Credential-Check: -' -d '{"username":"CF_EXPOSED_USERNAME", "password":"CF_EXPOSED_PASSWORD"}'
error code: 1020
以上、非常に簡単な内容でしたが、Cloudflare Leaked Credentials Check機能を触ってみたメモでした。
クラウドフレアでは不正認証対策として、本機能の他にもボットファイトモードやレート制限ルールなどが有効かと思いますので、このあたりの機能もうまく組み合わせてアプリケーションのセキュリティを向上させていきたいですね。
余談ですが、検証の過程で某Rockyouなリストから1万件ほど抽出し、ユーザ名をadminに固定してHydraを回してみたのですが、全く検知しませんでした。クラウドフレアBlog (Privacy-Preserving Compromised Credential Checking) にも踏み込んだ内容の記事がある通り、それなりの元ネタとしっかりと考慮された検知ロジックによって実装されていることが想像されます。