Version Description
- The filter files are now generated from PHPDoc in the code. There were too many times when the filters were out of sync with the code (programmer error) - this should resolve that by bringing the patterns closer to the code that emits them.
- Added PHPUnit tests. Almost 100% code coverage, with the exception of
WP_FAIL2BAN_PROXIES
which is quite hard to test properly. - Bugfix for
wordpress-soft.conf
. - Add
WP_FAIL2BAN_XMLRPC_LOG
. - Add
WP_FAIL2BAN_REMOTE_ADDR
. -
WP_FAIL2BAN_PROXIES
now supports an array of IPs with PHP 7. - Moved all documentation to https://wp-fail2ban.readthedocs.io/.
Download this release
Release Info
Developer | invisnet |
Plugin | WP fail2ban |
Version | 3.6.0 |
Comparing to | |
See all releases |
Code changes from version 3.5.3 to 3.6.0
- filters.d/wordpress-hard.conf +27 -26
- filters.d/wordpress-soft.conf +22 -31
- readme.txt +189 -301
- wp-fail2ban.php +165 -112
filters.d/wordpress-hard.conf
CHANGED
@@ -1,26 +1,27 @@
|
|
1 |
-
# Fail2Ban filter for WordPress hard failures
|
2 |
-
#
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
^%(__prefix_line)sBlocked
|
15 |
-
^%(__prefix_line)
|
16 |
-
^%(__prefix_line)
|
17 |
-
^%(__prefix_line)
|
18 |
-
^%(__prefix_line)
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
#
|
24 |
-
#
|
25 |
-
#
|
26 |
-
#
|
|
1 |
+
# Fail2Ban filter for WordPress hard failures
|
2 |
+
# Auto-generated: 2018-11-04T16:40:53+00:00
|
3 |
+
#
|
4 |
+
|
5 |
+
[INCLUDES]
|
6 |
+
|
7 |
+
before = common.conf
|
8 |
+
|
9 |
+
[Definition]
|
10 |
+
|
11 |
+
_daemon = (?:wordpress|wp)
|
12 |
+
|
13 |
+
failregex = ^%(__prefix_line)sBlocked authentication attempt for .* from <HOST>$
|
14 |
+
^%(__prefix_line)sBlocked user enumeration attempt from <HOST>$
|
15 |
+
^%(__prefix_line)sSpam comment \d+ from <HOST>$
|
16 |
+
^%(__prefix_line)sXML-RPC multicall authentication failure from <HOST>$
|
17 |
+
^%(__prefix_line)sPingback error .* generated from <HOST>$
|
18 |
+
^%(__prefix_line)sAuthentication attempt for unknown user .* from <HOST>$
|
19 |
+
^%(__prefix_line)sXML-RPC authentication attempt for unknown user .* from <HOST>$
|
20 |
+
|
21 |
+
ignoreregex =
|
22 |
+
|
23 |
+
# DEV Notes:
|
24 |
+
# Requires the 'WP fail2ban' plugin:
|
25 |
+
# https://github.com/invisnet/wp-fail2ban/
|
26 |
+
#
|
27 |
+
# Author: Charles Lecklider
|
filters.d/wordpress-soft.conf
CHANGED
@@ -1,31 +1,22 @@
|
|
1 |
-
# Fail2Ban
|
2 |
-
#
|
3 |
-
#
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
# Notes
|
19 |
-
#
|
20 |
-
#
|
21 |
-
#
|
22 |
-
#
|
23 |
-
#
|
24 |
-
failregex = ^%(__prefix_line)sAuthentication failure for .* from <HOST>$
|
25 |
-
^%(__prefix_line)sXML-RPC authentication failure from <HOST>$
|
26 |
-
|
27 |
-
# Option: ignoreregex
|
28 |
-
# Notes.: regex to ignore. If this regex matches, the line is ignored.
|
29 |
-
# Values: TEXT
|
30 |
-
#
|
31 |
-
ignoreregex =
|
1 |
+
# Fail2Ban filter for WordPress soft failures
|
2 |
+
# Auto-generated: 2018-11-04T16:40:53+00:00
|
3 |
+
#
|
4 |
+
|
5 |
+
[INCLUDES]
|
6 |
+
|
7 |
+
before = common.conf
|
8 |
+
|
9 |
+
[Definition]
|
10 |
+
|
11 |
+
_daemon = (?:wordpress|wp)
|
12 |
+
|
13 |
+
failregex = ^%(__prefix_line)sAuthentication failure for .* from <HOST>$
|
14 |
+
^%(__prefix_line)sXML-RPC authentication failure for .* from <HOST>$
|
15 |
+
|
16 |
+
ignoreregex =
|
17 |
+
|
18 |
+
# DEV Notes:
|
19 |
+
# Requires the 'WP fail2ban' plugin:
|
20 |
+
# https://github.com/invisnet/wp-fail2ban/
|
21 |
+
#
|
22 |
+
# Author: Charles Lecklider
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
readme.txt
CHANGED
@@ -1,301 +1,189 @@
|
|
1 |
-
=== WP fail2ban ===
|
2 |
-
Contributors: invisnet
|
3 |
-
Author URI: https://charles.lecklider.org/
|
4 |
-
Plugin URI: https://
|
5 |
-
Tags: fail2ban, login, security, syslog
|
6 |
-
Requires at least: 3.4
|
7 |
-
Tested up to: 4.
|
8 |
-
Stable tag: 3.
|
9 |
-
|
10 |
-
License
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
=
|
28 |
-
|
29 |
-
**CloudFlare and Proxy Servers**
|
30 |
-
|
31 |
-
*WPf2b* can be configured to work with CloudFlare and other proxy servers.
|
32 |
-
|
33 |
-
**Comments**
|
34 |
-
|
35 |
-
*WPf2b* can log comments. See `WP_FAIL2BAN_LOG_COMMENTS
|
36 |
-
|
37 |
-
**Pingbacks**
|
38 |
-
|
39 |
-
*WPf2b* logs failed pingbacks, and can log all pingbacks.
|
40 |
-
|
41 |
-
**Spam**
|
42 |
-
|
43 |
-
*WPf2b* can log comments marked as spam. See `WP_FAIL2BAN_LOG_SPAM`
|
44 |
-
|
45 |
-
**User Enumeration**
|
46 |
-
|
47 |
-
*WPf2b* can block user enumeration. See `WP_FAIL2BAN_BLOCK_USER_ENUMERATION`
|
48 |
-
|
49 |
-
**Work-Arounds for Broken syslogd**
|
50 |
-
|
51 |
-
*WPf2b* can be configured to work around most syslogd weirdness.
|
52 |
-
|
53 |
-
**Blocking Users**
|
54 |
-
|
55 |
-
*WPf2b* can be configured to short-cut the login process when the username matches a regex.
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
[
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
5.
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
=
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
=
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
=
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
*
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
=
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
By default, *WPf2b* uses LOG_AUTH for logging authentication success or failure. However, some systems use LOG_AUTHPRIV instead, but there's no good run-time way to tell. If your system uses LOG_AUTHPRIV you should add the following to `wp-config.php`:
|
191 |
-
|
192 |
-
define('WP_FAIL2BAN_AUTH_LOG',LOG_AUTHPRIV);
|
193 |
-
|
194 |
-
== Changelog ==
|
195 |
-
|
196 |
-
= 3.5.3 =
|
197 |
-
* Bugfix for `wordpress-hard.conf`.
|
198 |
-
|
199 |
-
= 3.5.1 =
|
200 |
-
* Bugfix for `WP_FAIL2BAN_BLOCK_USER_ENUMERATION`.
|
201 |
-
|
202 |
-
= 3.5.0 =
|
203 |
-
* Add `WP_FAIL2BAN_OPENLOG_OPTIONS`.
|
204 |
-
* Add `WP_FAIL2BAN_LOG_COMMENTS` and `WP_FAIL2BAN_COMMENT_LOG`.
|
205 |
-
* Add `WP_FAIL2BAN_LOG_PASSWORD_REQUEST`.
|
206 |
-
* Add `WP_FAIL2BAN_LOG_SPAM`.
|
207 |
-
* Add `WP_FAIL2BAN_TRUNCATE_HOST`.
|
208 |
-
* `WP_FAIL2BAN_BLOCKED_USERS` now supports an array of users with PHP 7.
|
209 |
-
|
210 |
-
= 3.0.3 =
|
211 |
-
* Fix regex in `wordpress-hard.conf`
|
212 |
-
|
213 |
-
= 3.0.2 =
|
214 |
-
* Prevent double logging in WP 4.5.x for XML-RPC authentication failure
|
215 |
-
|
216 |
-
= 3.0.1 =
|
217 |
-
* Fix regex in `wordpress-hard.conf`
|
218 |
-
|
219 |
-
= 3.0.0 =
|
220 |
-
* Add `WP_FAIL2BAN_SYSLOG_SHORT_TAG`.
|
221 |
-
* Add `WP_FAIL2BAN_HTTP_HOST`.
|
222 |
-
* Log XML-RPC authentication failure.
|
223 |
-
* Add better support for MU deployment.
|
224 |
-
|
225 |
-
= 2.3.2 =
|
226 |
-
* Bugfix `WP_FAIL2BAN_BLOCKED_USERS`.
|
227 |
-
|
228 |
-
= 2.3.0 =
|
229 |
-
* Bugfix in *experimental* `WP_FAIL2BAN_PROXIES` code (thanks to KyleCartmell).
|
230 |
-
|
231 |
-
= 2.2.1 =
|
232 |
-
* Fix stupid mistake with `WP_FAIL2BAN_BLOCKED_USERS`.
|
233 |
-
|
234 |
-
= 2.2.0 =
|
235 |
-
* Custom authentication log is now called `WP_FAIL2BAN_AUTH_LOG`
|
236 |
-
* Add logging for pingbacks
|
237 |
-
* Custom pingback log is called `WP_FAIL2BAN_PINGBACK_LOG`
|
238 |
-
|
239 |
-
= 2.1.1 =
|
240 |
-
* Minor bugfix.
|
241 |
-
|
242 |
-
= 2.1.0 =
|
243 |
-
* Add support for blocking user enumeration; see `WP_FAIL2BAN_BLOCK_USER_ENUMERATION`
|
244 |
-
* Add support for CIDR notation in `WP_FAIL2BAN_PROXIES`.
|
245 |
-
|
246 |
-
= 2.0.1 =
|
247 |
-
* Bugfix in *experimental* `WP_FAIL2BAN_PROXIES` code.
|
248 |
-
|
249 |
-
= 2.0.0 =
|
250 |
-
* Add *experimental* support for X-Forwarded-For header; see `WP_FAIL2BAN_PROXIES`
|
251 |
-
* Add *experimental* support for regex-based login blocking; see `WP_FAIL2BAN_BLOCKED_USERS`
|
252 |
-
|
253 |
-
= 1.2.1 =
|
254 |
-
* Update FAQ.
|
255 |
-
|
256 |
-
= 1.2 =
|
257 |
-
* Fix harmless warning.
|
258 |
-
|
259 |
-
= 1.1 =
|
260 |
-
* Minor cosmetic updates.
|
261 |
-
|
262 |
-
= 1.0 =
|
263 |
-
* Initial release.
|
264 |
-
|
265 |
-
== Upgrade Notice ==
|
266 |
-
|
267 |
-
= 3.5.3 =
|
268 |
-
You will need up update your `fail2ban` filters.
|
269 |
-
|
270 |
-
= 3.5.1 =
|
271 |
-
Bugfix: disable `WP_FAIL2BAN_BLOCK_USER_ENUMERATION` in admin area....
|
272 |
-
|
273 |
-
= 3.5.0 =
|
274 |
-
You will need up update your `fail2ban` filters.
|
275 |
-
|
276 |
-
= 3.0.3 =
|
277 |
-
You will need up update your `fail2ban` filters.
|
278 |
-
|
279 |
-
= 3.0.0 =
|
280 |
-
BREAKING CHANGE: The `fail2ban` filters have been split into two files. You will need up update your `fail2ban` configuration.
|
281 |
-
|
282 |
-
= 2.3.0 =
|
283 |
-
Fix for `WP_FAIL2BAN_PROXIES`; if you're not using it you can safely skip this release.
|
284 |
-
|
285 |
-
= 2.2.1 =
|
286 |
-
Bugfix.
|
287 |
-
|
288 |
-
= 2.2.0 =
|
289 |
-
BREAKING CHANGE: `WP_FAIL2BAN_LOG` has been renamed to `WP_FAIL2BAN_AUTH_LOG`
|
290 |
-
|
291 |
-
Pingbacks are getting a lot of attention recently, so *WPf2b* can now log them.
|
292 |
-
The `wordpress.conf` filter has been updated; you will need to update your `fail2ban` configuration.
|
293 |
-
|
294 |
-
= 2.1.0 =
|
295 |
-
The `wordpress.conf` filter has been updated; you will need to update your `fail2ban` configuration.
|
296 |
-
|
297 |
-
= 2.0.1 =
|
298 |
-
Bugfix in experimental code; still an experimental release.
|
299 |
-
|
300 |
-
= 2.0.0 =
|
301 |
-
This is an experimental release. If your current version is working and you're not interested in the new features, skip this version - wait for 2.1.0. For those that do want to test this release, note that `wordpress.conf` has changed - you'll need to copy it to `fail2ban/filters.d` again.
|
1 |
+
=== WP fail2ban ===
|
2 |
+
Contributors: invisnet
|
3 |
+
Author URI: https://charles.lecklider.org/
|
4 |
+
Plugin URI: https://github.com/invisnet/wp-fail2ban
|
5 |
+
Tags: fail2ban, login, security, syslog
|
6 |
+
Requires at least: 3.4
|
7 |
+
Tested up to: 4.9
|
8 |
+
Stable tag: 3.6.0
|
9 |
+
Requires PHP: 5.3
|
10 |
+
License: GPLv2 or later
|
11 |
+
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
12 |
+
Provides: FAIL2BAN
|
13 |
+
|
14 |
+
Write a myriad of WordPress events to syslog for integration with fail2ban.
|
15 |
+
|
16 |
+
== Description ==
|
17 |
+
|
18 |
+
[fail2ban](http://www.fail2ban.org/) is one of the simplest and most effective security measures you can implement to prevent brute-force password-guessing attacks.
|
19 |
+
|
20 |
+
*WP fail2ban* logs all login attempts - including via XML-RPC, whether successful or not, to syslog using LOG_AUTH. For example:
|
21 |
+
|
22 |
+
Oct 17 20:59:54 foobar wordpress(www.example.com)[1234]: Authentication failure for admin from 192.168.0.1
|
23 |
+
Oct 17 21:00:00 foobar wordpress(www.example.com)[2345]: Accepted password for admin from 192.168.0.1
|
24 |
+
|
25 |
+
*WPf2b* comes with two `fail2ban` filters, `wordpress-hard.conf` and `wordpress-soft.conf`, designed to allow a split between immediate banning and the traditional more graceful approach.
|
26 |
+
|
27 |
+
= Features =
|
28 |
+
|
29 |
+
**CloudFlare and Proxy Servers**
|
30 |
+
|
31 |
+
*WPf2b* can be configured to work with CloudFlare and other proxy servers. For an overview see [`WP_FAIL2BAN_PROXIES`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-proxies).
|
32 |
+
|
33 |
+
**Comments**
|
34 |
+
|
35 |
+
*WPf2b* can log comments. See [`WP_FAIL2BAN_LOG_COMMENTS`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-log-comments).
|
36 |
+
|
37 |
+
**Pingbacks**
|
38 |
+
|
39 |
+
*WPf2b* logs failed pingbacks, and can log all pingbacks. For an overview see [`WP_FAIL2BAN_LOG_PINGBACKS`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-log-pingbacks).
|
40 |
+
|
41 |
+
**Spam**
|
42 |
+
|
43 |
+
*WPf2b* can log comments marked as spam. See [`WP_FAIL2BAN_LOG_SPAM`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-log-spam).
|
44 |
+
|
45 |
+
**User Enumeration**
|
46 |
+
|
47 |
+
*WPf2b* can block user enumeration. See [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-block-user-enumeration).
|
48 |
+
|
49 |
+
**Work-Arounds for Broken syslogd**
|
50 |
+
|
51 |
+
*WPf2b* can be configured to work around most syslogd weirdness. For an overview see [`WP_FAIL2BAN_SYSLOG_SHORT_TAG`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-syslog-short-tag) and [`WP_FAIL2BAN_HTTP_HOST`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-http-host).
|
52 |
+
|
53 |
+
**Blocking Users**
|
54 |
+
|
55 |
+
*WPf2b* can be configured to short-cut the login process when the username matches a regex. For an overview see [`WP_FAIL2BAN_BLOCKED_USERS`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-blocked-users).
|
56 |
+
|
57 |
+
**`mu-plugins` Support**
|
58 |
+
|
59 |
+
*WPf2b* can easily be configured as a must-use plugin - see [Configuration](https://wp-fail2ban.readthedocs.io/en/3.6/configuration.html#mu-plugins-support).
|
60 |
+
|
61 |
+
|
62 |
+
|
63 |
+
== Installation ==
|
64 |
+
|
65 |
+
1. Install via the Plugin Directory, or upload to your plugins directory.
|
66 |
+
1. Activate the plugin through the 'Plugins' menu in WordPress.
|
67 |
+
1. Edit `wp-config.php` to suit your needs - see [Configuration](https://wp-fail2ban.readthedocs.io/en/3.6/configuration.html).
|
68 |
+
|
69 |
+
== Changelog ==
|
70 |
+
|
71 |
+
= 3.6.0 =
|
72 |
+
* The [filter files](https://wp-fail2ban.readthedocs.io/en/3.6/filters.html) are now generated from PHPDoc in the code. There were too many times when the filters were out of sync with the code (programmer error) - this should resolve that by bringing the patterns closer to the code that emits them.
|
73 |
+
* Added [PHPUnit tests](https://wp-fail2ban.readthedocs.io/en/3.6/tests.html). Almost 100% code coverage, with the exception of [`WP_FAIL2BAN_PROXIES`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-proxies) which is quite hard to test properly.
|
74 |
+
* Bugfix for [`wordpress-soft.conf`](https://wp-fail2ban.readthedocs.io/en/3.6/filters.html#wordpress-soft-conf).
|
75 |
+
* Add [`WP_FAIL2BAN_XMLRPC_LOG`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-xmlrpc-log).
|
76 |
+
* Add [`WP_FAIL2BAN_REMOTE_ADDR`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-remote-addr).
|
77 |
+
* [`WP_FAIL2BAN_PROXIES`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-proxies) now supports an array of IPs with PHP 7.
|
78 |
+
* Moved all documentation to [https://wp-fail2ban.readthedocs.io/](https://wp-fail2ban.readthedocs.io/).
|
79 |
+
|
80 |
+
= 3.5.3 =
|
81 |
+
* Bugfix for [`wordpress-hard.conf`](https://wp-fail2ban.readthedocs.io/en/3.6/filters.html#wordpress-hard-conf).
|
82 |
+
|
83 |
+
= 3.5.1 =
|
84 |
+
* Bugfix for [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-block-user-enumeration).
|
85 |
+
|
86 |
+
= 3.5.0 =
|
87 |
+
* Add [`WP_FAIL2BAN_OPENLOG_OPTIONS`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-openlog-options).
|
88 |
+
* Add [`WP_FAIL2BAN_LOG_COMMENTS`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-log-comments) and [`WP_FAIL2BAN_COMMENT_LOG`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-comment-log).
|
89 |
+
* Add [`WP_FAIL2BAN_LOG_PASSWORD_REQUEST`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-log-password-request).
|
90 |
+
* Add [`WP_FAIL2BAN_LOG_SPAM`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-log-spam).
|
91 |
+
* Add [`WP_FAIL2BAN_TRUNCATE_HOST`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-truncate-host).
|
92 |
+
* [`WP_FAIL2BAN_BLOCKED_USERS`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-blocked-users) now supports an array of users with PHP 7.
|
93 |
+
|
94 |
+
= 3.0.3 =
|
95 |
+
* Fix regex in [`wordpress-hard.conf`](https://wp-fail2ban.readthedocs.io/en/3.6/filters.html#wordpress-hard-conf).
|
96 |
+
|
97 |
+
= 3.0.2 =
|
98 |
+
* Prevent double logging in WP 4.5.x for XML-RPC authentication failure
|
99 |
+
|
100 |
+
= 3.0.1 =
|
101 |
+
* Fix regex in [`wordpress-hard.conf`](https://wp-fail2ban.readthedocs.io/en/3.6/filters.html#wordpress-hard-conf).
|
102 |
+
|
103 |
+
= 3.0.0 =
|
104 |
+
* Add [`WP_FAIL2BAN_SYSLOG_SHORT_TAG`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-syslog-short-tag).
|
105 |
+
* Add [`WP_FAIL2BAN_HTTP_HOST`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-http-host).
|
106 |
+
* Log XML-RPC authentication failure.
|
107 |
+
* Add better support for MU deployment.
|
108 |
+
|
109 |
+
= 2.3.2 =
|
110 |
+
* Bugfix [`WP_FAIL2BAN_BLOCKED_USERS`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-blocked-users).
|
111 |
+
|
112 |
+
= 2.3.0 =
|
113 |
+
* Bugfix in *experimental* [`WP_FAIL2BAN_PROXIES`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-proxies) code (thanks to KyleCartmell).
|
114 |
+
|
115 |
+
= 2.2.1 =
|
116 |
+
* Fix stupid mistake with [`WP_FAIL2BAN_BLOCKED_USERS`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-blocked-users).
|
117 |
+
|
118 |
+
= 2.2.0 =
|
119 |
+
* Custom authentication log is now called [`WP_FAIL2BAN_AUTH_LOG`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-auth-log).
|
120 |
+
* Add logging for pingbacks; see [`WP_FAIL2BAN_LOG_PINGBACKS`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-log-pingbacks).
|
121 |
+
* Custom pingback log is called [`WP_FAIL2BAN_PINGBACK_LOG`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-pingback-log).
|
122 |
+
|
123 |
+
= 2.1.1 =
|
124 |
+
* Minor bugfix.
|
125 |
+
|
126 |
+
= 2.1.0 =
|
127 |
+
* Add support for blocking user enumeration; see [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-block-user-enumeration).
|
128 |
+
* Add support for CIDR notation in [`WP_FAIL2BAN_PROXIES`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-proxies).
|
129 |
+
|
130 |
+
= 2.0.1 =
|
131 |
+
* Bugfix in *experimental* [`WP_FAIL2BAN_PROXIES`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-proxies) code.
|
132 |
+
|
133 |
+
= 2.0.0 =
|
134 |
+
* Add *experimental* support for X-Forwarded-For header; see [`WP_FAIL2BAN_PROXIES`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-proxies).
|
135 |
+
* Add *experimental* support for regex-based login blocking; see [`WP_FAIL2BAN_BLOCKED_USERS`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-blocked-users).
|
136 |
+
|
137 |
+
= 1.2.1 =
|
138 |
+
* Update FAQ.
|
139 |
+
|
140 |
+
= 1.2 =
|
141 |
+
* Fix harmless warning.
|
142 |
+
|
143 |
+
= 1.1 =
|
144 |
+
* Minor cosmetic updates.
|
145 |
+
|
146 |
+
= 1.0 =
|
147 |
+
* Initial release.
|
148 |
+
|
149 |
+
== Upgrade Notice ==
|
150 |
+
|
151 |
+
= 3.6.0 =
|
152 |
+
You will need up update your `fail2ban` filters.
|
153 |
+
|
154 |
+
= 3.5.3 =
|
155 |
+
You will need up update your `fail2ban` filters.
|
156 |
+
|
157 |
+
= 3.5.1 =
|
158 |
+
Bugfix: disable [`WP_FAIL2BAN_BLOCK_USER_ENUMERATION`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-block-user-enumeration) in admin area....
|
159 |
+
|
160 |
+
= 3.5.0 =
|
161 |
+
You will need up update your `fail2ban` filters.
|
162 |
+
|
163 |
+
= 3.0.3 =
|
164 |
+
You will need up update your `fail2ban` filters.
|
165 |
+
|
166 |
+
= 3.0.0 =
|
167 |
+
BREAKING CHANGE: The `fail2ban` filters have been split into two files. You will need up update your `fail2ban` configuration.
|
168 |
+
|
169 |
+
= 2.3.0 =
|
170 |
+
Fix for [`WP_FAIL2BAN_PROXIES`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-proxies); if you're not using it you can safely skip this release.
|
171 |
+
|
172 |
+
= 2.2.1 =
|
173 |
+
Bugfix.
|
174 |
+
|
175 |
+
= 2.2.0 =
|
176 |
+
BREAKING CHANGE: `WP_FAIL2BAN_LOG` has been renamed to [`WP_FAIL2BAN_AUTH_LOG`](https://wp-fail2ban.readthedocs.io/en/3.6/defines.html#wp-fail2ban-auth-log).
|
177 |
+
|
178 |
+
Pingbacks are getting a lot of attention recently, so *WPf2b* can now log them.
|
179 |
+
The `wordpress.conf` filter has been updated; you will need to update your `fail2ban` configuration.
|
180 |
+
|
181 |
+
= 2.1.0 =
|
182 |
+
The `wordpress.conf` filter has been updated; you will need to update your `fail2ban` configuration.
|
183 |
+
|
184 |
+
= 2.0.1 =
|
185 |
+
Bugfix in experimental code; still an experimental release.
|
186 |
+
|
187 |
+
= 2.0.0 =
|
188 |
+
This is an experimental release. If your current version is working and you're not interested in the new features, skip this version - wait for 2.1.0. For those that do want to test this release, note that `wordpress.conf` has changed - you'll need to copy it to `fail2ban/filters.d` again.
|
189 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wp-fail2ban.php
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
<?php
|
2 |
-
|
3 |
* Plugin Name: WP fail2ban
|
4 |
-
* Plugin URI: https://
|
5 |
-
* Description: Write
|
6 |
* Text Domain: wp-fail2ban
|
7 |
-
* Version: 3.
|
8 |
* Author: Charles Lecklider
|
9 |
* Author URI: https://charles.lecklider.org/
|
10 |
* License: GPL2
|
11 |
* SPDX-License-Identifier: GPL-2.0
|
12 |
*/
|
13 |
|
14 |
-
|
15 |
-
* Copyright 2012-
|
16 |
*
|
17 |
* This program is free software; you can redistribute it and/or modify
|
18 |
* it under the terms of the GNU General Public License, version 2, as
|
@@ -36,16 +36,17 @@ namespace org\lecklider\charles\wordpress\wp_fail2ban;
|
|
36 |
*/
|
37 |
global $wp_fail2ban;
|
38 |
if (empty($wp_fail2ban) && defined('WP_FAIL2BAN')) return;
|
39 |
-
define('WP_FAIL2BAN',true);
|
40 |
|
41 |
|
42 |
/**
|
43 |
-
* Allow custom openlog
|
44 |
-
* e.g. you may not want the PID if logging remotely.
|
45 |
-
* @since 3.5.0
|
|
|
46 |
*/
|
47 |
if (!defined('WP_FAIL2BAN_OPENLOG_OPTIONS')) {
|
48 |
-
define('WP_FAIL2BAN_OPENLOG_OPTIONS', LOG_PID);
|
49 |
}
|
50 |
/**
|
51 |
* Make sure all custom logs are defined.
|
@@ -67,12 +68,12 @@ if (!defined('WP_FAIL2BAN_PINGBACK_LOG')) {
|
|
67 |
*/
|
68 |
function openlog($log = 'WP_FAIL2BAN_AUTH_LOG')
|
69 |
{
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
/**
|
77 |
* Some varieties of syslogd have difficulty if $host is too long
|
78 |
* @since 3.5.0
|
@@ -80,10 +81,10 @@ function openlog($log = 'WP_FAIL2BAN_AUTH_LOG')
|
|
80 |
if (defined('WP_FAIL2BAN_TRUNCATE_HOST') && 1 < intval(WP_FAIL2BAN_TRUNCATE_HOST)) {
|
81 |
$host = substr($host, 0, intval(WP_FAIL2BAN_TRUNCATE_HOST));
|
82 |
}
|
83 |
-
|
84 |
-
error_log('WPf2b: Cannot open syslog', 0);
|
85 |
-
} elseif (defined('
|
86 |
-
error_log('WPf2b: Opened syslog', 0);
|
87 |
}
|
88 |
}
|
89 |
|
@@ -98,9 +99,9 @@ function syslog($level, $msg, $remote_addr = null)
|
|
98 |
: $remote_addr;
|
99 |
|
100 |
if (false === \syslog($level, $msg)) {
|
101 |
-
error_log("WPf2b: Cannot write to syslog: '{$msg}'", 0);
|
102 |
-
} elseif (defined('
|
103 |
-
error_log("WPf2b: Wrote to syslog: '{$msg}'", 0);
|
104 |
}
|
105 |
\closelog();
|
106 |
|
@@ -117,38 +118,57 @@ function syslog($level, $msg, $remote_addr = null)
|
|
117 |
*/
|
118 |
function bail()
|
119 |
{
|
120 |
-
|
121 |
}
|
122 |
|
|
|
|
|
|
|
|
|
123 |
function remote_addr()
|
124 |
{
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
}
|
147 |
|
148 |
|
149 |
/**
|
150 |
* @since 2.0.0
|
151 |
* @since 3.5.0 Refactored for unit testing
|
|
|
|
|
152 |
*/
|
153 |
function authenticate($user, $username, $password)
|
154 |
{
|
@@ -168,9 +188,9 @@ function authenticate($user, $username, $password)
|
|
168 |
}
|
169 |
|
170 |
return $user;
|
171 |
-
}
|
172 |
if (defined('WP_FAIL2BAN_BLOCKED_USERS')) {
|
173 |
-
|
174 |
}
|
175 |
|
176 |
|
@@ -178,6 +198,8 @@ if (defined('WP_FAIL2BAN_BLOCKED_USERS')) {
|
|
178 |
* @since 2.1.0
|
179 |
* @since 3.5.0 Refactored for unit testing
|
180 |
* @since 3.5.1 Check is_admin
|
|
|
|
|
181 |
*/
|
182 |
if (defined('WP_FAIL2BAN_BLOCK_USER_ENUMERATION') && true === WP_FAIL2BAN_BLOCK_USER_ENUMERATION) {
|
183 |
function parse_request($query)
|
@@ -190,23 +212,7 @@ if (defined('WP_FAIL2BAN_BLOCK_USER_ENUMERATION') && true === WP_FAIL2BAN_BLOCK_
|
|
190 |
|
191 |
return $query;
|
192 |
}
|
193 |
-
|
194 |
-
}
|
195 |
-
|
196 |
-
|
197 |
-
/**
|
198 |
-
* @since 2.2.0
|
199 |
-
* @since 3.5.0 Refactored for unit testing
|
200 |
-
*/
|
201 |
-
if (defined('WP_FAIL2BAN_LOG_PINGBACKS') && true === WP_FAIL2BAN_LOG_PINGBACKS) {
|
202 |
-
function xmlrpc_call($call)
|
203 |
-
{
|
204 |
-
if ('pingback.ping' == $call) {
|
205 |
-
openlog('WP_FAIL2BAN_PINGBACK_LOG');
|
206 |
-
syslog(LOG_INFO, 'Pingback requested');
|
207 |
-
}
|
208 |
-
}
|
209 |
-
add_action('xmlrpc_call', __NAMESPACE__.'\xmlrpc_call');
|
210 |
}
|
211 |
|
212 |
|
@@ -227,27 +233,29 @@ if (defined('WP_FAIL2BAN_LOG_COMMENTS') && true === WP_FAIL2BAN_LOG_COMMENTS) {
|
|
227 |
|
228 |
/**
|
229 |
* @since 3.5.0
|
|
|
|
|
230 |
*/
|
231 |
if (defined('WP_FAIL2BAN_LOG_SPAM') && true === WP_FAIL2BAN_LOG_SPAM) {
|
232 |
-
|
233 |
{
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
* @todo: decide what to do about this
|
238 |
*/
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
}
|
252 |
|
253 |
|
@@ -260,7 +268,77 @@ if (defined('WP_FAIL2BAN_LOG_PASSWORD_REQUEST') && true === WP_FAIL2BAN_LOG_PASS
|
|
260 |
openlog();
|
261 |
syslog(LOG_NOTICE, "Password reset requested for {$user_login}");
|
262 |
}
|
263 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
}
|
265 |
|
266 |
|
@@ -279,6 +357,11 @@ add_action('wp_login', __NAMESPACE__.'\wp_login', 10, 2);
|
|
279 |
/**
|
280 |
* @since 1.0.0
|
281 |
* @since 3.5.0 Refactored for unit testing
|
|
|
|
|
|
|
|
|
|
|
282 |
*/
|
283 |
function wp_login_failed($username)
|
284 |
{
|
@@ -295,33 +378,3 @@ function wp_login_failed($username)
|
|
295 |
}
|
296 |
add_action('wp_login_failed', __NAMESPACE__.'\wp_login_failed');
|
297 |
|
298 |
-
|
299 |
-
/**
|
300 |
-
* @since 3.0.0
|
301 |
-
* @since 3.5.0 Refactored for unit testing
|
302 |
-
*/
|
303 |
-
function xmlrpc_login_error($error, $user)
|
304 |
-
{
|
305 |
-
static $attempts = 0;
|
306 |
-
|
307 |
-
if (++$attempts > 1) {
|
308 |
-
openlog();
|
309 |
-
syslog(LOG_NOTICE, 'XML-RPC multicall authentication failure');
|
310 |
-
bail();
|
311 |
-
}
|
312 |
-
}
|
313 |
-
add_action('xmlrpc_login_error', __NAMESPACE__.'\xmlrpc_login_error', 10, 2);
|
314 |
-
|
315 |
-
|
316 |
-
/**
|
317 |
-
* @since 3.0.0
|
318 |
-
* @since 3.5.0 Refactored for unit testing
|
319 |
-
*/
|
320 |
-
function xmlrpc_pingback_error($ixr_error)
|
321 |
-
{
|
322 |
-
if (48 === $ixr_error->code)
|
323 |
-
return $ixr_error;
|
324 |
-
openlog();
|
325 |
-
syslog(LOG_NOTICE, 'Pingback error '.$ixr_error->code.' generated');
|
326 |
-
}
|
327 |
-
add_filter('xmlrpc_pingback_error', __NAMESPACE__.'\xmlrpc_pingback_error', 5);
|
1 |
<?php
|
2 |
+
/*
|
3 |
* Plugin Name: WP fail2ban
|
4 |
+
* Plugin URI: https://github.com/invisnet/wp-fail2ban
|
5 |
+
* Description: Write a myriad of WordPress events to syslog for integration with fail2ban.
|
6 |
* Text Domain: wp-fail2ban
|
7 |
+
* Version: 3.6.0
|
8 |
* Author: Charles Lecklider
|
9 |
* Author URI: https://charles.lecklider.org/
|
10 |
* License: GPL2
|
11 |
* SPDX-License-Identifier: GPL-2.0
|
12 |
*/
|
13 |
|
14 |
+
/*
|
15 |
+
* Copyright 2012-18 Charles Lecklider (email : wordpress@charles.lecklider.org)
|
16 |
*
|
17 |
* This program is free software; you can redistribute it and/or modify
|
18 |
* it under the terms of the GNU General Public License, version 2, as
|
36 |
*/
|
37 |
global $wp_fail2ban;
|
38 |
if (empty($wp_fail2ban) && defined('WP_FAIL2BAN')) return;
|
39 |
+
define('WP_FAIL2BAN', true);
|
40 |
|
41 |
|
42 |
/**
|
43 |
+
* Allow custom openlog options.
|
44 |
+
* e.g. you may not want the PID if logging remotely.
|
45 |
+
* @since 3.5.0
|
46 |
+
* @since 3.6.0 Add LOG_NDELAY
|
47 |
*/
|
48 |
if (!defined('WP_FAIL2BAN_OPENLOG_OPTIONS')) {
|
49 |
+
define('WP_FAIL2BAN_OPENLOG_OPTIONS', LOG_PID|LOG_NDELAY);
|
50 |
}
|
51 |
/**
|
52 |
* Make sure all custom logs are defined.
|
68 |
*/
|
69 |
function openlog($log = 'WP_FAIL2BAN_AUTH_LOG')
|
70 |
{
|
71 |
+
$tag = (defined('WP_FAIL2BAN_SYSLOG_SHORT_TAG') && true === WP_FAIL2BAN_SYSLOG_SHORT_TAG)
|
72 |
+
? 'wp' // @codeCoverageIgnore
|
73 |
+
: 'wordpress';
|
74 |
+
$host = (array_key_exists('WP_FAIL2BAN_HTTP_HOST', $_ENV))
|
75 |
+
? $_ENV['WP_FAIL2BAN_HTTP_HOST'] // @codeCoverageIgnore
|
76 |
+
: $_SERVER['HTTP_HOST'];
|
77 |
/**
|
78 |
* Some varieties of syslogd have difficulty if $host is too long
|
79 |
* @since 3.5.0
|
81 |
if (defined('WP_FAIL2BAN_TRUNCATE_HOST') && 1 < intval(WP_FAIL2BAN_TRUNCATE_HOST)) {
|
82 |
$host = substr($host, 0, intval(WP_FAIL2BAN_TRUNCATE_HOST));
|
83 |
}
|
84 |
+
if (false === \openlog("$tag($host)", WP_FAIL2BAN_OPENLOG_OPTIONS, constant($log))) {
|
85 |
+
error_log('WPf2b: Cannot open syslog', 0); // @codeCoverageIgnore
|
86 |
+
} elseif (defined('WP_FAIL2BAN_TRACE')) {
|
87 |
+
error_log('WPf2b: Opened syslog', 0); // @codeCoverageIgnore
|
88 |
}
|
89 |
}
|
90 |
|
99 |
: $remote_addr;
|
100 |
|
101 |
if (false === \syslog($level, $msg)) {
|
102 |
+
error_log("WPf2b: Cannot write to syslog: '{$msg}'", 0); // @codeCoverageIgnore
|
103 |
+
} elseif (defined('WP_FAIL2BAN_TRACE')) {
|
104 |
+
error_log("WPf2b: Wrote to syslog: '{$msg}'", 0); // @codeCoverageIgnore
|
105 |
}
|
106 |
\closelog();
|
107 |
|
118 |
*/
|
119 |
function bail()
|
120 |
{
|
121 |
+
wp_die('Forbidden', 'Forbidden', array('response' => 403));
|
122 |
}
|
123 |
|
124 |
+
/**
|
125 |
+
* @todo Test me!
|
126 |
+
* @codeCoverageIgnore
|
127 |
+
*/
|
128 |
function remote_addr()
|
129 |
{
|
130 |
+
if (defined('WP_FAIL2BAN_PROXIES')) {
|
131 |
+
if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
|
132 |
+
$ip = ip2long($_SERVER['REMOTE_ADDR']);
|
133 |
+
/**
|
134 |
+
* PHP 7 lets you define an array
|
135 |
+
* @since 3.5.4
|
136 |
+
*/
|
137 |
+
$proxies = (is_array(WP_FAIL2BAN_PROXIES))
|
138 |
+
? WP_FAIL2BAN_PROXIES
|
139 |
+
: explode(',', WP_FAIL2BAN_PROXIES);
|
140 |
+
foreach ($proxies as $proxy) {
|
141 |
+
if (2 == count($cidr = explode('/', $proxy))) {
|
142 |
+
$net = ip2long($cidr[0]);
|
143 |
+
$mask = ~ ( pow(2, (32 - $cidr[1])) - 1 );
|
144 |
+
} else {
|
145 |
+
$net = ip2long($proxy);
|
146 |
+
$mask = -1;
|
147 |
+
}
|
148 |
+
if ($net == ($ip & $mask)) {
|
149 |
+
return (false === ($len = strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',')))
|
150 |
+
? $_SERVER['HTTP_X_FORWARDED_FOR']
|
151 |
+
: substr($_SERVER['HTTP_X_FORWARDED_FOR'], 0, $len);
|
152 |
+
}
|
153 |
+
}
|
154 |
+
}
|
155 |
+
}
|
156 |
+
|
157 |
+
/**
|
158 |
+
* For plugins and themes that anonymise requests
|
159 |
+
* @since 3.6.0
|
160 |
+
*/
|
161 |
+
return (defined('WP_FAIL2BAN_REMOTE_ADDR'))
|
162 |
+
? WP_FAIL2BAN_REMOTE_ADDR
|
163 |
+
: $_SERVER['REMOTE_ADDR'];
|
164 |
}
|
165 |
|
166 |
|
167 |
/**
|
168 |
* @since 2.0.0
|
169 |
* @since 3.5.0 Refactored for unit testing
|
170 |
+
*
|
171 |
+
* @wp-f2b-hard Blocked authentication attempt for .*
|
172 |
*/
|
173 |
function authenticate($user, $username, $password)
|
174 |
{
|
188 |
}
|
189 |
|
190 |
return $user;
|
191 |
+
}
|
192 |
if (defined('WP_FAIL2BAN_BLOCKED_USERS')) {
|
193 |
+
add_filter('authenticate', __NAMESPACE__.'\authenticate', 1, 3);
|
194 |
}
|
195 |
|
196 |
|
198 |
* @since 2.1.0
|
199 |
* @since 3.5.0 Refactored for unit testing
|
200 |
* @since 3.5.1 Check is_admin
|
201 |
+
*
|
202 |
+
* @wp-f2b-hard Blocked user enumeration attempt
|
203 |
*/
|
204 |
if (defined('WP_FAIL2BAN_BLOCK_USER_ENUMERATION') && true === WP_FAIL2BAN_BLOCK_USER_ENUMERATION) {
|
205 |
function parse_request($query)
|
212 |
|
213 |
return $query;
|
214 |
}
|
215 |
+
add_filter('parse_request', __NAMESPACE__.'\parse_request', 1, 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
216 |
}
|
217 |
|
218 |
|
233 |
|
234 |
/**
|
235 |
* @since 3.5.0
|
236 |
+
*
|
237 |
+
* @wp-f2b-hard Spam comment \d+
|
238 |
*/
|
239 |
if (defined('WP_FAIL2BAN_LOG_SPAM') && true === WP_FAIL2BAN_LOG_SPAM) {
|
240 |
+
function log_spam_comment($comment_id, $comment_status)
|
241 |
{
|
242 |
+
if ('spam' === $comment_status) {
|
243 |
+
if (is_null($comment = get_comment($comment_id, ARRAY_A))) {
|
244 |
+
/**
|
245 |
* @todo: decide what to do about this
|
246 |
*/
|
247 |
+
} else {
|
248 |
+
$remote_addr = (empty($comment['comment_author_IP']))
|
249 |
+
? 'unknown' // @codeCoverageIgnore
|
250 |
+
: $comment['comment_author_IP'];
|
251 |
+
|
252 |
+
openlog();
|
253 |
+
syslog(LOG_INFO, "Spam comment {$comment_id}", $remote_addr);
|
254 |
+
}
|
255 |
+
}
|
256 |
+
};
|
257 |
+
add_action('comment_post', __NAMESPACE__.'\log_spam_comment', 10, 2);
|
258 |
+
add_action('wp_set_comment_status', __NAMESPACE__.'\log_spam_comment', 10, 2);
|
259 |
}
|
260 |
|
261 |
|
268 |
openlog();
|
269 |
syslog(LOG_NOTICE, "Password reset requested for {$user_login}");
|
270 |
}
|
271 |
+
add_action('retrieve_password', __NAMESPACE__.'\retrieve_password');
|
272 |
+
}
|
273 |
+
|
274 |
+
|
275 |
+
if (defined('XMLRPC_REQUEST') && true === XMLRPC_REQUEST) {
|
276 |
+
/**
|
277 |
+
* @since 3.0.0
|
278 |
+
* @since 3.5.0 Refactored for unit testing
|
279 |
+
*
|
280 |
+
* @wp-f2b-hard XML-RPC multicall authentication failure
|
281 |
+
*/
|
282 |
+
function xmlrpc_login_error($error, $user)
|
283 |
+
{
|
284 |
+
static $attempts = 0;
|
285 |
+
|
286 |
+
if (++$attempts > 1) {
|
287 |
+
openlog();
|
288 |
+
syslog(LOG_NOTICE, 'XML-RPC multicall authentication failure');
|
289 |
+
bail();
|
290 |
+
}
|
291 |
+
}
|
292 |
+
add_action('xmlrpc_login_error', __NAMESPACE__.'\xmlrpc_login_error', 10, 2);
|
293 |
+
|
294 |
+
|
295 |
+
/**
|
296 |
+
* @since 3.0.0
|
297 |
+
* @since 3.5.0 Refactored for unit testing
|
298 |
+
*
|
299 |
+
* @wp-f2b-hard Pingback error .* generated
|
300 |
+
*/
|
301 |
+
function xmlrpc_pingback_error($ixr_error)
|
302 |
+
{
|
303 |
+
if (48 === $ixr_error->code) return $ixr_error; // @codeCoverageIgnore
|
304 |
+
openlog();
|
305 |
+
syslog(LOG_NOTICE, 'Pingback error '.$ixr_error->code.' generated');
|
306 |
+
}
|
307 |
+
add_filter('xmlrpc_pingback_error', __NAMESPACE__.'\xmlrpc_pingback_error', 5);
|
308 |
+
|
309 |
+
|
310 |
+
/**
|
311 |
+
* @since 2.2.0
|
312 |
+
* @since 3.5.0 Refactored for unit testing
|
313 |
+
*/
|
314 |
+
if (defined('WP_FAIL2BAN_LOG_PINGBACKS') && true === WP_FAIL2BAN_LOG_PINGBACKS) {
|
315 |
+
function xmlrpc_call($call)
|
316 |
+
{
|
317 |
+
if ('pingback.ping' == $call) {
|
318 |
+
openlog('WP_FAIL2BAN_PINGBACK_LOG');
|
319 |
+
syslog(LOG_INFO, 'Pingback requested');
|
320 |
+
}
|
321 |
+
}
|
322 |
+
add_action('xmlrpc_call', __NAMESPACE__.'\xmlrpc_call');
|
323 |
+
}
|
324 |
+
|
325 |
+
|
326 |
+
/**
|
327 |
+
* Log XML-RPC requests
|
328 |
+
*
|
329 |
+
* It seems attackers are doing weird things with XML-RPC. This makes it easy to
|
330 |
+
* log them for analysis and future blocking.
|
331 |
+
*
|
332 |
+
* @since 3.6.0
|
333 |
+
*/
|
334 |
+
if (defined('WP_FAIL2BAN_XMLRPC_LOG')) {
|
335 |
+
if (false === ($fp = fopen(WP_FAIL2BAN_XMLRPC_LOG, 'a+'))) {
|
336 |
+
// TODO: decided whether to log this
|
337 |
+
} else {
|
338 |
+
fprintf($fp, "# ---\n# Date: %s\n# IP: %s\n\n%s\n", date(DATE_ATOM), remote_addr(), $HTTP_RAW_POST_DATA);
|
339 |
+
fclose($fp);
|
340 |
+
}
|
341 |
+
}
|
342 |
}
|
343 |
|
344 |
|
357 |
/**
|
358 |
* @since 1.0.0
|
359 |
* @since 3.5.0 Refactored for unit testing
|
360 |
+
*
|
361 |
+
* @wp-f2b-hard Authentication attempt for unknown user .*
|
362 |
+
* @wp-f2b-hard XML-RPC authentication attempt for unknown user .*
|
363 |
+
* @wp-f2b-soft Authentication failure for .*
|
364 |
+
* @wp-f2b-soft XML-RPC authentication failure for .*
|
365 |
*/
|
366 |
function wp_login_failed($username)
|
367 |
{
|
378 |
}
|
379 |
add_action('wp_login_failed', __NAMESPACE__.'\wp_login_failed');
|
380 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|