🗝️

Laravel ログイン後にパスワード漏洩チェックを掛けるという発想

2022/03/18に公開

前書き

(少し長めの前書きですが…)

先日、とあるふるさと納税サイトが、「パスワードリスト攻撃」に遭い、個人情報が流出したという記事が掲載されていました。
ふるさと納税サイトが600万回のリスト型攻撃で被害、2000件超の個人情報流出か

「パスワードリスト攻撃」とは、下記のサイトによると
https://www.f5.com/ja_jp/services/resources/glossary/password-attack

あらかじめ入手してリスト化したIDとパスワードを利用し、Webサイトへの不正アクセスを試みるという攻撃方法

要は他のサイトで使われたメルアドとパスワードが漏洩して、そのリストを使って、ログインを試みてくるという手法ですね。「ブルートフォース(総当たり)攻撃」と比べると遙かに効率がいい攻撃と言え、ブルートフォースと比べると検出が難しくなるようです。

で、上記の場合

主に日本国内の 2,000 以上の IP アドレスから分散して約 600 万回行われた。

そうです。

Laravel のログインにも throttle 機能があったりしますが、それは、ログインID(メルアド)とIPアドレスのセットでカウントしていて、ログインIDが異なると、別人としてカウントされるので、今回のような場合、意味無い気がします。

かと言って、単純にIPアドレスだけの制限にするとアプリの性質によっては、例えば、社員が100人いる組織で、1つのグローバルIPアドレスで運用されている場合、朝9時、誰かがログインに連続して失敗して throttle に引っかかると、他の社員も皆ログインできなくなったりして、もうパニック状態になりそうです。

結論としては、WAFを入れたり、2要素認証を導入して必須にしなよ、とかなったりしますが、政治的、予算的事情などでうまく行かないこともあるかと思います。

WAFと言えば、つい先日、CloudFlareが IPアドレス(のみ)に頼らないWAFというのを記事で紹介していました。

Introducing Advanced Rate Limiting

で、その辺の記事を斜め読みしていてふと思ったのが、Laravel でもパスワードの漏洩チェックできる機能はあったりしますが、基本 validation の機能なので、「会員登録する際」に使うものとしか考えていませんでしたが、考えてみれば、「ログイン後」にもその機能を使う事は可能な訳ですね。

もちろん、ログイン認証する手前でも走らせる事は可能ですが、攻撃がある事を考えれば、必要以上に外部APIを叩くのは避けなければならないので、「ログイン後」としています。

パスワード漏洩機能については、以前私の書いた記事を参考にして下さい。
Laravel 新しい Password ルールオブジェクトを試してみる。そして軽くショックを受ける。

で、結局何?

つまり、会員が認証OKでログインした後に、パスワード漏洩チェックを掛け、そのパスワードが漏洩していた場合、ログアウトさせ、パスワード再発行の案内画面(発行画面ではなく)へ誘導する事にします。

やや厳しい処理だとは思いますが、まぁ、そこは諦めてもらうしかありません。
問題は、ユーザーにその辺をどう説明するか、ですが…。😩

こうする事で、仮に悪い人達が漏洩済みのパスワードを使ってログインに成功しても、実際は何もできないままになり、個人情報の漏洩は防げます。
(もちろん、パスワード漏洩チェックに引っかかれば、の話ですが)
(また、ログインできるという情報は知られますが、それは避けられないというか…)

もし「ログイン情報を記憶する」機能を使ってログインする場合は、元のパスワードは分かりませんので、漏洩チェックに掛ける事はできませんが、悪い人達はIDとパスワードを使ってログインするという前提なので、そこはいいかと思います。

コード上で簡易に表現すると、下記のようになります。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Validation\Rules\Password;

class LoginController extends Controller
{
    public function index(Request $request)
    {
        // まずはバリデーションをする
        $request->validate([
            'email' => 'xxx',
            'password' => 'xxx',
        ]);

        if (認証NGで、ログインに失敗した場合) {
            // ログイン画面へリダイレクト
        }

        // 認証は通ったが、更に 漏洩チェックを掛ける。

        $password = 'abcd1234'; // ユーザーが入力したパスワード

        $validator = validator(
            ['password' => $password],
            ['password' => Password::min(8)->uncompromised()]
        );

        if ($validator->fails()) {
            // パスワードが漏洩している場合、ここに来るので、
            // まずはログアウトの状態にする。
            // 場合によっては、アカウントをロックしたりとかも。

            // パスワード再発行の案内画面(発行画面ではなく)へリダイレクトする
	    // (正規のユーザーしか再発行できないようにする)
            return redirect('xxx');
        }

        // 以下、今度こそログインOK
	
    }
}

以上です。

もちろん、新規会員登録時もパスワード漏洩チェックは掛ける想定です。

余談

そのパスワード漏洩チェックサービスを提供している方、ちょっとしたミスで、Microsoft Azure から高額請求(93万)を受ける事になってしまったという記事がありました。

https://gigazine.net/news/20220126-have-i-been-pwned-cost/

「サイトの運営大丈夫だろうか…😨」とか一瞬思ったりしましたが、Twitter みたら、リッチそうな方だったので、大丈夫だと思います。😀

とは言え、サービスを利用するときは、寄付を募っているので、是非検討したいですね。

雑感

ちなみに個人的には、ベネッセ(しまじろう)のシステムが分からなすぎて、小学2年になる息子を2重で登録してしまい、教材がダブってくるというハプニングを起こしたばかりの私でした。😂

間違いやミス、ご意見等ありましたらコメント下さい。

Discussion