By the example of WordPress consider a method for enhancing security by limiting the number of HTTP-requests to the form of entering the password. This helps protect against brute force published a blog (search and crack the password by trying all possible scenarios of a particular set of characters, or the selection of a dictionary of common passwords). This method, in principle, can be used to protect other Web applications.
The task can be realized using Nginx module ngx_http_limit_req_module [1] acts as a front-end to the Apache Web server or FastCGI, or via HAProxy [2, 3], acts as a load balancer in front of web servers.
In both cases, the algorithm works as follows. When authentication browser refer to the addresses containing the substring “/wp-login.php”. It is necessary to keep track of it and to limit the number of requests from the same IP without affecting circulation to all other addresses. Block settings must be chosen in such way as not to create a normal user inconvenience. Especially attentively should be configured to lock when the authorization form uses a large number of users with the same IP-address.
Method №1: Nginx
http {
<...>
limit_req_zone $binary_remote_addr zone=login:10m rate=15r/m;
server {
listen 80;
server_name frontend.example.org;
location ~* /wp-login.php {
limit_req zone=login burst=4;
proxy_pass http://backend:8080;
<...>
}
location / {
proxy_pass http://backend:8080;
<...>
}
}
Block settings:
limit_req_zone $binary_remote_addr zone=login: 10m rate=15r/m; Sets an area of shared memory, which stores the state for different IP-addresses. In our case, the state is stored in the zone “login” size of 10 megabytes, and the average speed of query processing for the zone can not exceed 15 requests per minute. The processing speed can be specified in requests per second (r/s) or requests per minute (r/m).
limit_req zone=login burst=4; sets the login area and the maximum size of the burst of requests. If the requests rate higher than described in the area, their processing is delayed so that the request is being processed at a given speed. Excessive requests are delayed as long as their number does not exceed the maximum size of the burst. When exceeding the request fails with the error 503.
Method №2: HAProxy
In this section of the backend, serving our blog, add the following lines [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
Upon detection of POST-request to the page /wp-login.php saved hash of three elements: header HTTP Host, URL-path and IP source. Identified on the basis of the hash the user can make requests for five to 20 seconds, the sixth request will be blocked.
Sourses
- Module ngx_http_limit_req_module – nginx.org
- http://blog.haproxy.com/2013/04/26/wordpress-cms-brute-force-protection-with-haproxy/ – blog.haproxy.com
- Better Rate Limiting For All with HAProxy – blog.serverfault.com
This text is a translation of the article “Ограничение количества попыток ввода пароля в веб-форме авторизации при помощи Ngnix или HAProxy на примере WordPress” published by foboss on habrahabr.ru.