sorceryのブルートフォースアタック対策モジュールを使ってみた

Rails 4.0.0.rc1
sorcery (0.8.1)

はじめに

ブルートフォースアタックとは、手当たり次第パスワードの入力を試みる攻撃方法。こわいです。
(http://ja.wikipedia.org/wiki/総当たり攻撃)

sorceryとは

シンプル認証ライブラリ。
コア以外の機能は、サブモジュールとして選択しないと有効にならない。
以下がそのサブモジュール。

  • パスワードリセット
  • アクティビティロギング(最後にログインした日、最後にログアウトした日、最後にアクティビティのある日をカラムに自動で記録する)
  • Omniauth的なやつ
  • アクティベーション(メール送ってリンク踏んだらアカウント有効化する)
  • remember me(いつまでログイン状態を維持するか)
  • 総当たり攻撃対策

sorceryで総当たり攻撃対策

最近、sorceryという認証系ライブラリを使っています。
このsorceryには、総当たり攻撃対策のモジュールが組み込まれていて、簡単にアプリに実装することができました。
この対策モジュールでやることは、(自分で設定した)ログイン連続失敗回数を超えると、アカウントをロックしてログインできなくする。
ロックの解除には、2つ方法があって、時間経過とメールでロック解除URLを送ることもできるようです。

サブモジュールを有効する手順

  1. config/initializers/sorcery.rbに使うモジュールを書く
  2. config/initializers/sorcery.rbに設定内容を書く(サブモジュールで使うカラム名を変更したりできる)
  3. User系モデルに必要なカラムを追加する

だけ

(1)config/initializers/sorcery.rbに使うモジュールを書く

# config/initializers/sorcery.rb
Rails.application.config.sorcery.submodules = [:brute_force_protection] 

5行名に使いたいモジュール名を書く。使えるモジュールは3,4行目に書いているのでそれをコピペする・

(2)config/initializers/sorcery.rbに設定内容を書く

ありがたいことに設定内容を自分で書かなくてもデフォルト設定があるので書かなくても動く。
自分の場合は数字を変更したかったので以下のようにした。

# config/initializers/sorcery.rb
    # -- brute_force_protection --
    # Failed logins attribute name.
    # Default: `:failed_logins_count`
    #
    # user.failed_logins_count_attribute_name =
                                                                                                                                                              

    # This field indicates whether user is banned and when it will be active again.
    # Default: `:lock_expires_at`
    #
    # user.lock_expires_at_attribute_name =


    # How many failed logins allowed.
    # Default: `50`
    #
     user.consecutive_login_retries_amount_limit = 5
    # How long the user should be banned. in seconds. 0 for permanent.
    # Default: `60 * 60`
    #
    user.login_lock_time_period = 1.day

このモジュールで使うカラムはデフォルト名をそのまま使いたいので、コメントのままにし、
5回連続ログイン失敗でロック。24時間経過したらロック解除するようにした。メールでのロック解除は使わない。

(3)User系モデルに必要なカラムを追加する

このモジュールで使うカラムは、現在の連続失敗回数とロックした時の日時を格納する2つのカラムが必要。
デフォルトで使われるカラム名は以下となってる。

class AddBruteForceProtectionToUsers < ActiveRecord::Migration
  def change
    add_column :users, :failed_logins_count, :integer, default: 0
    add_column :users, :lock_expires_at, :datetime
  end 
end 

以上で、総当たり攻撃対策ができた。ありがたやありがたや。
ロックがかかるとlock_expires_atカラムに日付が入る。時間が経過してからログインをもう一度失敗すると、
lock_expires_atにnilが入り、認証できるようになる。
時間を待たずに認証できるようするには、lock_expires_atカラムにnilを入れればよい。

以下のサンプルプロジェクトがすごくわかりやすかったです。
https://github.com/NoamB/sorcery-example-app