[Solved] Possible feature: authentication brute force hardening
I was looking into how lighttpd could be hardened against brute forcing authentication credentials. Unfortunately, I initially missed the forum and filed the idea as a ticket. You can find the ticket at https://redmine.lighttpd.net/issues/2997, but discussion should continue here. Let me summarise the main results from the ticket here:
- It would be nice if lighttpd could make it harder for attackers to brute force http authentication credentials. Such a feature should be optional and disabled by default (at least for now).
- Different setups have different trade-offs here. For some preventing brute force is more imporant than preventing DoS, but not all. Likely this trade-off should be configurable.
- It should be possible to make the mitigation per-ip and per-user.
- It can be implemented either inside lighttpd or externally (e.g. using fail2ban). For the latter, lighttpd would have to distinguish stale/missing digest auth nonces from actual failures in its logs (possible by logging the whole header using mod_accesslog).
- Other measures outside the realm of lighttpd should be considered. Using strong passwords and using something other than "admin" as username.
- There appear to be two major use cases:
- Internet servers. Blocks should be per-ip and per-user such that one client cannot easily deny service to another. Possibly blocks should be widened to subnets to reduce the impact of botnets.
- Embedded devices. It can be assumed that the network is hostile and denial of service can be easily performed. The focus should be on preventing unauthenticated access.
- Delaying failed authentication attempts.
- Denying all authentication attempts when authentication failures happen too quickly. This approach risks clients retrying indefinitely and consuming more resources.
I hope that this accurately represents the views expressed in the ticket discussion.This gives rise to the following questions:
- Is there general interest in this feature? How many users would benefit from it? (i.e. is it worth investing more effort at all?)
- If the previous answer is positive, is such a feature generally in scope of lighttpd or should it be implemented externally or not at all?
- If the previous answer is positive, what are the actual requirements for getting it into lighttpd? What aspects am I missing above? Which need to be dropped?
One item that you appear to have overlooked is that lighttpd mod_fastcgi supports
mode = "authorizer", so that lighttpd will delegate the authorization to a backend FastCGI, which can be implemented however you like, including arbitrary mitigations, and no changes are necessary to lighttpd.
For something to be accepted into lighttpd, it should be generically useful, and there must be a strong reason why implementing as a FastCGI backend is infeasible. The FastCGI backend could be written in C, and as small and fast as the lighttpd optional mod_authn*. As such, this option is viable for embedded systems.
I am more likely to accept small patches into lighttpd which minimally adjust error logging so that it is easier to use with fail2ban or similar programs.
On an untrusted network, strong authentication mechanisms and TLS should be preferred, if not required. A simple protection against brute force attacks is that the embedded device itself is probably not powerful enough to perform TLS and modern crypto at an extremely high rate. Combined with a unique username (not the default "admin") and a strong password, and this combination of best practices may be sufficient for many users, without any additional changes to lighttpd.
Thank you for pointing out the delegation option. I take that as "Is there general interest in this feature? -> No", which is fine.
For others who might read this, would you mind posting the rate at which your embedded device can respond to brute force password attacks while running lighttpd 1.4.54 with mod_openssl for TLS, and mod_auth using
"algorithm" => "SHA-256" ? The rate is probably lower than you think.
Currently, lighttpd allows retries after a 401 Unauthorized over a keep-alive connection. Perhaps lighttpd should issue
Connection: close after a bad password (as opposed to a missing Authorization request header). That would slow down brute force retries. If you disable keep-alive with
server.max-keep-alive-requests = 0, how much does doing so affect the rate at which your embedded device can respond to brute force password attacks?
Edit: my laptop (quad-core Intel i7 from a few years ago) can barely do 200 requests per second with
ab -c 4 (Apache bench) using TLS and
"algorithm" => "SHA-256" without keep-alive, but can do 60,000 requests per second with keep-alive
ab -c 4 -k
=> Closing the connection after a bad password seems like an easy and worthwhile mitigation.
RE: [Solved] Possible feature: authentication brute force hardening - Added by gstrauss about 1 year ago
lighttpd 1.4.55 mod_auth now closes the connection after a bad password attempt, disallowing keep-alive after bad password. This slows down password brute-force attempts, especially when the connection is over TLS.