2017-05-17 17 views
0

Definitive guide to form based website authenticationは、迅速なログイン試行を防ぐために読んでいます。Rack :: Attackによる迅速なログイン試行の防止

この一例は次のようになります。

  • 1等試み=
  • 2回失敗遅延なし= 2秒の遅延
  • 3試み= 4秒の遅延を失敗
に失敗

他の方法もガイドに表示されていますが、すべて失敗した試みを記録できる記憶域が必要です。

ブロックリストは、this issue(ブロックリストに変更された古い名前のブラックリストの下に表示されています)の投稿の1つで議論されています。ラックあたりのよう

::アタック具体的には、実装の一素朴な例は次のようになります。

ログインに失敗した

ラックattack.rbで
StorageMechanism.increment("bad-login/#{req.ip") 

Rack::Attack.blacklist('bad-logins') { |req| 
    StorageMechanism.get("bad-login/#{req.ip}") 
} 

ここには2つの部分があり、ブロックリストに含まれている場合は応答を返し、前回の失敗した試行があったかどうかを確認します(StorageMechanism)。

応答を返す最初の部分は、gemによって自動的に処理されます。しかし、少なくとも宝石とRailsの世界であるRedisのキャッシュバックエンドのための事実上の選択では、2番目の部分はあまり明確ではありません。

私が知る限り、Redisの期限切れの鍵は自動的に削除されます。そうすれば情報にアクセスすることができなくなり(期限切れの場合でも)、カウンタに新しい値を設定し、それに応じて不応期のタイムアウトを増やします。

RedisとRack :: Attackでこれを達成する方法はありますか?

「StorageMechanism」は、このケースでは絶対に無関係なままで、Rack :: Attackとそのストレージの選択について何も知らないと考えていました。

+1

'ラック:: Attack'は通常* *絞る大量の要求に使用されます。私は "3失敗試行= 4秒遅れ"のようなルールを厳格すぎると見なします。 [example configurations](https://github.com/kickstarter/rack-attack/wiki/Example-Configuration)を読んでください。あなたがここで達成しようとしていることは、[指数的バックオフ](https://github.com/kickstarter/rack-attack/wiki/Advanced-Configuration#exponential-backoff)でうまくいくと思います。 –

+0

ちょっと@TomLord、あなたのフィードバックのために大変感謝します。私はそれがあまりにも厳しいという同じ感情を持っています。とにかく、私は設定例を読んだが、指数バックオフは私に同じ質問を残す。この場合、リソース(ログイン)にはまだスロットルがありますが、特に失敗したシステムにはペナルティを課すことはありません。ガイドに記載されている技術の目的は理解しています。 – IoChaos

+1

'throttle'の代わりに' blacklist'を使うことができます。これは、その例のコードとほとんど同じコードです。私は以前に実動アプリケーションでこれを正確に使用しました。助けがあれば、このコードを掘り下げて下に貼り付けることができましたか? –

答えて

1

ご連絡が遅れて申し訳ありません。これに関連する私の古いコードを掘り起こすのに私はしばらくかかりました。上記のコメントで述べたように

は、ここにあなたがあなたの特定のアプリケーションのために必要に応じて、これらの数字を微調整したい場合がありfindtime

# config/initilizers/rack-attack.rb 
class Rack::Attack 
    (1..6).each do |level| 
    blocklist("allow2ban login scrapers - level #{level}") do |req| 
     Allow2Ban.filter( 
     req.ip, 
     maxretry: (20 * level), 
     findtime: (8**level).seconds, 
     bantime: (8**level).seconds 
    ) do 
     req.path == '/users/sign_in' && req.post? 
     end 
    end 
    end 
end 

blacklistを使用してソリューションです。上記の数値は、私の特定のアプリケーションにとって「賢明」と決めたものに過ぎません。公式な標準から来ていないのです。

アプリケーションを開発/テストするとき(例えば、rspecテストスイートの場合)、上記の制限に簡単にぶつかり、不注意にを調整することができます。これは、初期化に次の設定を追加することで回避できます。

safelist('allow from localhost') do |req| 
    '127.0.0.1' == req.ip || '::1' == req.ip 
end 

最も一般的なブルートフォースログイン攻撃は、攻撃者は、単にかどうかを確認するために電子メールやパスワードの多数を試みるブルートフォースパスワード攻撃であります任意の資格情報が一致します。

いくつかのログイン試行に失敗した後で、アカウントLOCKを使用してアプリケーションでこれを軽減する必要があります。 (例えば、deviseを使用している場合、そこで内蔵のあなたが利用することができLockable module。)

しかし、このアカウントロック的なアプローチは、新たな攻撃ベクトル開きます。攻撃者は、ログイン試行でシステムをスパムすることができますが、有効な電子メールと間違ったパスワードを使用して、すべてのアカウントを継続的に再ロックしてください!

この設定では、特定のIPからのサインイン試行回数を指数関数的にに制限することができます。

は、私はまた、次の「キャッチオール」要求スロットル追加:

throttle('req/ip', limit: 300, period: 5.minutes, &:ip) 

これは、悪質な/悪い構成されたスクレーパを絞る主です。それらがアプリサーバーのすべてのCPUを大量に消費することを防ぎます。

注:ラック経由でアセットを提供している場合、ラックアタックによってアセットがカウントされ、このスロットルがすぐにアクティブになることがあります。その場合は、条件を有効にしてトラッキングから除外します。


また、私のRack::Attack構成がその仕事をしていることを確認するための統合テストを書いています。そここのテスト作業を行うにはいくつかの課題があったので、私はコード+コメントが自身のために話すもらおう:

class Rack::AttackTest < ActionDispatch::IntegrationTest 
    setup do 
    # Prevent subtle timing issues (==> intermittant test failures) 
    # when the HTTP requests span across multiple seconds 
    # by FREEZING TIME(!!) for the duration of the test 
    travel_to(Time.now) 

    @removed_safelist = Rack::Attack.safelists.delete('allow from localhost') 
    # Clear the Rack::Attack cache, to prevent test failure when 
    # running multiple times in quick succession. 
    # 
    # First, un-ban localhost, in case it is already banned after a previous test: 
    (1..6).each do |level| 
     Rack::Attack::Allow2Ban.reset('127.0.0.1', findtime: (8**level).seconds) 
    end 
    # Then, clear the 300-request rate limiter cache: 
    Rack::Attack.cache.delete("#{Time.now.to_i/5.minutes}:req/ip:127.0.0.1") 
    end 

    teardown do 
    travel_back # Un-freeze time 
    Rack::Attack.safelists['allow from localhost'] = @removed_safelist 
    end 

    test 'should block access on 20th successive /users/sign_in attempt' do 
    19.times do |i| 
     post user_session_url 
     assert_response :success, "was not even allowed to TRY to login on attempt number #{i + 1}" 
    end 

    # For DOS protection: Don't even let the user TRY to login; they're going way too fast. 
    # Rack::Attack returns 403 for blocklists by default, but this can be reconfigured: 
    # https://github.com/kickstarter/rack-attack/blob/master/README.md#responses 
    post user_session_url 
    assert_response :forbidden, 'login access should be blocked upon 20 successive attempts' 
    end 
end 
関連する問題