Nginx Auth_Basic の再試行を制限するにはどうすればいいですか?

Nginx Auth_Basic の再試行を制限するにはどうすればいいですか?

Nginx の Auth_Basic モジュールを使用して Web フォルダーを保護しました。問題は、パスワードが機能するまで複数のパスワードを試すことができることです (ブルート フォース攻撃)。再試行の失敗回数を制限する方法はありますか?

答え1

私の知る限りでは、認証基本モジュールはこの機能をサポートしていませんが、フェイル2バン

存在しないユーザーでテストすると、エラー ログに次のような内容が表示されます。

2012/08/25 10:07:01 [error] 5866#0: *1 no user/password was provided for basic authentication, client: 127.0.0.1, server: localhost, request: "GET /pma HTTP/1.1", host: "localhost:81" 2012/08/25 10:07:04 [error] 5866#0: *1 user "ajfkla" was not found in "/etc/nginx/htpasswd", client: 127.0.0.1, server: localhost, request: "GET /pma HTTP/1.1", host: "localhost:81"

次に必要なフィルターを作成します。

/etc/fail2ban/filter.d/nginx-auth.conf

[Definition]
failregex = no user/password was provided for basic authentication.*client: <HOST>
              user .* was not found in.*client: <HOST>
              user .* password mismatch.*client: <HOST>
ignoreregex = </host></host></host> 

/etc/fail2ban/jail.conf

[nginx-auth]
enabled = true
filter = nginx-auth
action = iptables[name=NoAuthFailures, port=80, protocol=tcp]
logpath = /var/log/nginx*/*error*.log
bantime = 3600 # 1 hour
maxretry = 3

Fail2Ban ルールのテスト:

fail2ban-regex /var/log/nginx/localhost.error_log /etc/fail2ban/filter.d/nginx-auth.conf

Failregex
|- Regular expressions:
|  [1] no user/password was provided for basic authentication.*client: <HOST>
|  [2] user .* was not found in.*client: <HOST>
|  [3] user .* password mismatch.*client: <HOST>
|
`- Number of matches:
   [1] 1 match(es)
   [2] 2 match(es)
   [3] 0 match(es)

Ignoreregex
|- Regular expressions:
|
`- Number of matches:

Summary
=======

Addresses found:
[1]
    127.0.0.1 (Sat Aug 25 10:07:01 2012)
[2]
    127.0.0.1 (Sat Aug 25 10:07:04 2012)
    127.0.0.1 (Sat Aug 25 10:07:07 2012)
[3]

PS: Fail2ban は禁止するためにログ ファイルを取得するので、logpath設定と一致していることを確認してください。

答え2

他の誰もこの解決策/回避策を提示していないことに驚いています。

Nginx は、基本認証とhtpasswdオプションのコスト変数を使用した bcrypt パスワード暗号化をサポートします。bcrypt は低速になるように設計されているため、異なるパスワードを試行できる速度に厳しい制限が設けられています。

基本認証のユーザー名/パスワードを作成するときは、

htpasswd -B -C 12 path/to/users.db <username>

コストが 12 の場合、サーバーは 1 秒間に数回以上パスワードを試行できない可能性があります。コストを 14 に増やすと、パスワード試行ごとに約 1 秒かかる可能性があります。

このように設定すると、攻撃者が何年も継続的にパスワードを試行したとしても、適切なパスワードであればブルート フォース攻撃の影響を受けません。

たとえば、1 秒あたり 10 回のパスワード試行で、8 文字の英数字パスワードに対するブルート フォース攻撃には 692,351 年かかります62**8 / (10*3600*24*365)

これは、「インテリジェントな」リクエスト制限を設定するよりもはるかに簡単に構成でき、より確実です。

答え3

nginxにはこれを実行する内部機能はないと思います。ドキュメントページそれが可能であることを示唆するものではありません。

Fail2Ban を使用すると、ログイン試行が繰り返し失敗した IP アドレスをブロックできます。

Fail2Ban wikiにはnginx固有のパターン

Fail2Ban は、ほとんどの主要ディストリビューションでパッケージとして利用できるはずです。

答え4

これは、NGINX 基本認証とレート制限を組み合わせることで実現できます。

http {
    map $http_cookie $rate_limit_key {
        default $binary_remote_addr;
        "~__Secure-rl-bypass=SomeRandomBytes" "";
    }
    limit_req_status 429;
    limit_req_zone $rate_limit_key zone=auth:10m rate=1r/m;

    server {
            auth_basic "Private Content";
            auth_basic_user_file your-auth-file.txt;

            limit_req zone=auth burst=20 delay=10;

            add_header Set-Cookie "__Secure-rl-bypass=SomeRandomBytes;Max-Age=${toString (3600*24*180)};Domain=$host;Path=/;Secure;HttpOnly";
    }
}

このスニペットは私の作業構成から抽出されましたが、スニペット自体はテストされていません。

基本的な概念は、レート制限を回避できる Cookie を作成し、認証に成功したらその Cookie を設定することです。この方法では、ログインするまではレート制限が適用され、ログインした時点では必要な数のリクエストを実行できます。

このアプローチの主な欠点は、クッキーが静的であるため、誰かがいずれかのアカウントにログインすると、そのトークンを使用して他のアカウントをブルート フォース攻撃できることです。ユーザーが他のユーザーのパスワードをブルート フォース攻撃しないことが信頼されている場合、これは大きな問題ではありません。ただし、NGINX の設定でこれよりも優れた方法はないと思います。理想的には、クッキーはhash("$remote_user-SomeRandomBytes")トークンが正常にログインしたユーザーにバインドされるようにします。

関連情報