Обмеження кількості спроб введення пароля веб-формою авторизації WordPress за допомогою Nginx або HAProxy

Розглянемо на прикладі WordPress спосіб посилення безпеки за допомогою обмеження кількості HTTP-запитів до форми введення пароля. Це дозволить захистити опублікований блог від брутфорса (пошуку і злому пароля шляхом перебору всіх теоретично можливих варіантів з певного набору символів або підбору за словником поширених паролів). Даний спосіб, в принципі, можна використовувати і для захисту інших веб-додатків.

Задача може бути реалізована в Nginx з допомогою модуля ngx_http_limit_req_module [1], виступаючому в ролі фронт-енду до Apache або веб-сервера FastCGI, або ж з допомогою HAProxy [2, 3], виступаючому в ролі балансувальника навантаження перед веб-серверами.

В обох випадках алгоритм роботи наступний. При аутентифікації браузер звертається за адресою, що містить в собі підрядок "/wp-login.php". Необхідно відстежити її і обмежити кількість запитів з однієї IP не зачіпаючи звернення за всіма іншими адресами. Параметри блокування необхідно підібрати таким чином, щоб не створювати незручностей звичайними користувачами. Особливо уважно слід налаштовувати блокування в тому випадку, коли формою авторизації користується велика кількість користувачів з однієї IP-адреси.

Спосіб №1: Nginx
http {
<...>

limit_req_zone $binary_remote_addr zone=login:10m rate=15r/m;

server {
listen 80;
server_name frontend.example.org;

location / {
if ( $request_uri ~* /wp-login.php) {
return 405;
}
if ( $request_uri !~* /wp-login.php) {
return 406;
}

error_page 405 = @login;
error_page 406 = @data;
}

location @login {
limit_req zone=login burst=4;
proxy_pass http://backend:8080;
<...>
}

location @data {
proxy_pass http://backend:8080;
<...>
}
}

Параметри блокування:

limit_req_zone $binary_remote_addr zone=login:10m rate=15r/m; Задає параметри зони поділюваної пам'яті, яка зберігає стан для різних IP-адрес. У нашому випадку стану зберігаються у зоні «login» розміром 10 мегабайт, і середня швидкість обробки запитів для цієї зони не може перевищувати 15 запитів в хвилину. Швидкість обробки можна задати в запитах в секунду (r/s) або в запитах в хвилину (r/m).

limit_req zone=login burst=4; встановлює зону login і максимальний розмір сплеску запитів (burst). Якщо швидкість надходження запитів перевищує описану в зоні, то їх обробка затримується так, щоб запити оброблялися із заданою швидкістю. Надмірні запити затримуються до тих пір, поки їх кількість не перевищить максимальний розмір сплеску. При перевищенні запит завершується з помилкою 503.

Спосіб №2: HAProxy

У секцію backend, обслуговуючу наш блог, додаємо наступні рядки [2]:
tcp-request inspect-delay 10s
tcp-request content accept if HTTP
# brute force protection
acl wp_login path_beg-i /wp-login.php
stick-table type binary len 20 size 500 store http_req_rate(20s) peers local
tcp-request content track-sc2 base32+src if METH_POST wp_login
stick store-request base32+src if METH_POST wp_login
acl bruteforce_detection sc2_http_req_rate gt 5
acl flag_bruteforce sc1_inc_gpc0 gt 0
http request deny if bruteforce_detection flag_bruteforce

При виявленні POST-запити до сторінки /wp-login.php зберігається хеш з трьох елементів: заголовка HTTP Host, URL-шляхи і IP джерела. Ідентифікується на основі хеш користувач зможе зробити п'ять запитів за 20 секунд; шостий запит буде заблоковано.

Література
  1. Модуль ngx_http_limit_req_module — nginx.org
  2. wordpress CMS brute force protection with HAProxy — blog.haproxy.com
  3. Better Rate Limiting For All with HAProxy — blog.serverfault.com


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.