> > I updated
https://github.com/Exim/exim/wiki/BlockCracking
> When I review the code, I realize I must be using a slightly older version
> of it. Specifically, I do not have the lines:
>
> Acl_check_connect
>
> hash:
> accept set acl_c_authhash = ${nhash_1000:$acl_arg1}
>
> and
>
> acl_check_auth
> ...
> accept set acl_c_authhash = ${if match{$smtp_command_argument}\
> {\N(?i)^(?:plain|login) (.+)$\N}{${nhash_1000:$1}}}
>
> Could you explain them briefly? I am most concerned with the "accept set
> acl_c_authhash" above.
Somebody on this list expressed concern about the scenario:
an user is behind NAT in a small office router
($sender_host_address is the same for all computers in the office),
the user's mail client remembers wrong password (mistyped or changed),
the user presses the "send+retrieve mail" button several times in a row
(ignoring the error), as a result the whole office is blocked.
So, my updated code computes hash of a string containing username and password.
The hash is a number between 0 and 999. If the hash is the same
during all recent attempts from the same IP-address
then authentication failure is deemed benign (the same wrong password
tried multiple times), the IP-address isn't blocked. If a malicious bot
tries multiple usernames or passwords then hashes are different
almost every time, so the bot's IP-address is blocked.
In cases of Exim versions before 4.82 the code has access only to
the arguments of the AUTH command. Sometimes the AUTH command contains
base64-encoded username and password, sometimes it doesn't
(then username and password are transmitted separately).
But the protection against blocking benign authentication failures
works at least sometimes. On updated version of that webpage I wrote:
| If you use Exim version 4.82 or higher then after the string
| "begin authenticators" in the paragraph with PLAIN append
| (without a blank) at the very end of server_condion line:
| ${acl{hash}{$auth2,$auth3}} and in the paragraph with LOGIN
| append at the very end of server_condition line:
| ${acl{hash}{$auth1,$auth2}} . For example:
|
| server_condition = ${if pam{$auth2:${sg{$auth3}{:}{::}}}}${acl{hash}{$auth2,$auth3}}
That passes username and password to the "hash" ACL, it overwrites
$acl_c_authhash with hash or decoded username and password in any case.
Password is never stored. Hash of username and failed password
(a number between 0 and 999) is stored in $spool_directory/db/ratelimit
for about 2 weeks IIRC.