Community Auth has had a feature for some time that locks a person from attempting to login if they exceed a defined amount of login attempts. When that person waits 10 minutes, or however long you configure the waiting time, the person can then attempt to login once again. This works great, but if somebody bypasses the form and attempts to login via a script, Community Auth will at some point attempt to deny access to the IP address where those requests are coming from.

This feature may or may not be all that useful, but as it was before v3.1.0, a bug in the regular expression (regex) that rebuilds the deny list could render a site completely unusable. The condition leading to such a case would be brought about by an .htaccess file that is of medium to large filesize.

The Bad Regex

There are a few problems with this regex. It is using a greedy quantifier, the quantifier is inside a capturing group, and the PCRE library will smash the stack trying to remember everything. This leads to preg_replace outputting an empty string without any warning.

Some Better Regex

$pattern = '/(?<=# BEGIN DENY LIST --).*?(?=# END DENY LIST --)/s';

Here I’ve added a question mark, making the quantifier non-greedy, removed the capturing group, and used the s flag instead of .|\n. This regex can now handle much larger input, and this is the quick fix you need to apply if you don’t want to update to v3.1.0.

Rebuilding the Deny List Without preg_replace

The best solution may not even include a regular expression and preg_replace at all. Assuming we will always have our deny list at the top of our .htaccess file, Community Auth now splits the contents of the .htaccess file using PHP’s explode function. Everything after “# END DENY LIST –” is “captured” in a simple array element, and the freshly rebuilt deny list is prepended to it. There are other slight modifications to the method, so here is the current version: