mirror of https://github.com/fail2ban/fail2ban
DOC: developing filters without DoS
parent
9d4b613ee4
commit
ee786671aa
87
DEVELOP
87
DEVELOP
|
@ -41,8 +41,91 @@ Filters
|
|||
example.com/example.org used for DNS names
|
||||
* Ensure ./fail2ban-regex testcases/files/logs/{samplelog} config/filter.d/{filter}.conf
|
||||
has matches for EVERY regex
|
||||
* Ensure regexs end with a $ and are restrictive as possible. E.g. not .* if
|
||||
[0-9]+ is sufficient
|
||||
* Ensure regexs start with a ^ and are restrictive as possible. E.g. not .* if
|
||||
\d+ is sufficient
|
||||
* Use the functionality of regexs http://docs.python.org/2/library/re.html
|
||||
* Take a look at the source code of the application. You may see optional or
|
||||
extra log messages, or parts there of, that need to form part of your regex.
|
||||
|
||||
If you only have a basic knowledge of regular repressions read
|
||||
http://docs.python.org/2/library/re.html first.
|
||||
|
||||
Filter Security
|
||||
---------------
|
||||
|
||||
Poor filter regular expressions are suseptable to DoS attacks.
|
||||
|
||||
When a remote user has the ability to introduce text that will match the
|
||||
filter regex such that the inserted text matches the <HOST> part they have the
|
||||
ability to deny any host they choose.
|
||||
|
||||
So the <HOST> part must be anchored on text generated by the application and not
|
||||
the user. Ideally this should anchor to the beginning and end of the log line
|
||||
however as more applications log at the beginning than the end, achoring the
|
||||
beginning is more important.
|
||||
|
||||
When creating a regex that extends back to the begining remember the date part
|
||||
has been removed within fail2ban so theres no need to match that. If the format
|
||||
is like '<date...> error 1.2.3.4 is evil' then you will need to match the < at
|
||||
the start so here the regex would start like '^<> <HOST> is evil$'.
|
||||
|
||||
Some applications log spaces at the end. If you're not sure add \s*$ as the
|
||||
end part of the regex.
|
||||
|
||||
Examples of poor filters
|
||||
------------------------
|
||||
|
||||
1. Too restrictive
|
||||
|
||||
We find a log message:
|
||||
|
||||
Apr-07-13 07:08:36 Invalid command fial2ban from 1.2.3.4
|
||||
|
||||
We make a failregex
|
||||
|
||||
^Invalid command \S+ from <HOST>
|
||||
|
||||
Now think evil. The user does the command 'blah from 1.2.3.44'
|
||||
|
||||
The program diliently logs:
|
||||
|
||||
Apr-07-13 07:08:36 Invalid command blah from 1.2.3.44 from 1.2.3.4
|
||||
|
||||
And fail2ban matches 1.2.3.44 as the IP that it ban. A DoS attack was successful.
|
||||
|
||||
The fix here is that the command can be anything so .* is approprate.
|
||||
|
||||
^Invalid command .* from <HOST>
|
||||
|
||||
Here the .* will match until the end of the string. Then realise it has more to
|
||||
match, i.e. "from <HOST>" and go back until it find this. Then it will ban
|
||||
1.2.3.4 correctly. Since the <HOST> is always at the end, end the regex witha $
|
||||
|
||||
^Invalid command .* from <HOST>$
|
||||
|
||||
Note if we'd just had the expression:
|
||||
|
||||
^Invalid command \S+ from <HOST>$
|
||||
|
||||
Then provided the user put a space in their command they would have never been
|
||||
banned.
|
||||
|
||||
2. Applicaiton generates two identical log messages with different meanings
|
||||
|
||||
If the application generates the following two messages under different
|
||||
circmstances:
|
||||
|
||||
client <IP>: authentication failed
|
||||
client <USER>: authentication failed
|
||||
|
||||
|
||||
Then its obvious that a regex of "^client <HOST>: authentication
|
||||
failed$" will still cause problems if the user can trigger the second
|
||||
log message with a <USER> of 123.1.1.1.
|
||||
|
||||
Here there's nothing to do except request/change the application so it logs
|
||||
messages differently.
|
||||
|
||||
|
||||
Code Testing
|
||||
============
|
||||
|
|
Loading…
Reference in New Issue