WP fail2ban - Version 3.0.0

Version Description

  • Add WP_FAIL2BAN_SYSLOG_SHORT_TAG.
  • Add WP_FAIL2BAN_HTTP_HOST.
  • Log XML-RPC authentication failure.
  • Add better support for MU deployment.
Download this release

Release Info

Developer invisnet
Plugin Icon 128x128 WP fail2ban
Version 3.0.0
Comparing to
See all releases

Code changes from version 2.3.2 to 3.0.0

readme.txt CHANGED
@@ -1,90 +1,83 @@
1
- === WP fail2ban ===
2
- Contributors: invisnet
3
- Author URI: https://charles.lecklider.org/
4
- Plugin URI: https://charles.lecklider.org/wordpress/wp-fail2ban/
5
- Tags: fail2ban, security, syslog, login
6
- Requires at least: 3.4.0
7
- Tested up to: 4.3.1
8
- Stable tag: 2.3.2
9
- License: GPLv2 or later
10
- License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
-
12
- Write all login attempts to syslog for integration with fail2ban.
13
-
14
- == Description ==
15
-
16
  [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.
17
 
18
  *WP fail2ban* logs all login attempts, whether successful or not, to syslog using LOG_AUTH. To make log parsing as simple as possible *WPf2b* uses the same format as sshd. For example:
19
 
20
- Oct 17 20:59:54 foobar wordpress(www.example.com)[1234]: Authentication failure for admin from 192.168.0.1
21
- Oct 17 21:00:00 foobar wordpress(www.example.com)[2345]: Accepted password for admin from 192.168.0.1
22
-
23
- *WP fail2ban* can also log all pingbacks.
24
-
25
- *WPf2b* comes with a `fail2ban` filter, `wordpress.conf`.
26
-
27
- Requires PHP 5.3 or later.
28
-
29
- == Installation ==
30
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  1. Upload the plugin to your plugins directory
32
  1. Activate the plugin through the 'Plugins' menu in WordPress
33
  1. Copy `wordpress.conf` to your `fail2ban/filters.d` directory
34
  1. Edit `jail.local` to include something like:
35
-
36
- `[wordpress]`
37
- `enabled = true`
38
- `port = http,https`
39
- `filter = wordpress`
40
- `logpath = /var/log/auth.log`
41
-
42
- 1. Reload or restart `fail2ban`
43
-
44
- You may want to set WP_FAIL2BAN_BLOCK_USER_ENUMERATION, WP_FAIL2BAN_PROXIES and/or WP_FAIL2BAN_BLOCKED_USERS; see the FAQ for details.
45
-
46
- == Frequently Asked Questions ==
47
-
48
- = WP_FAIL2BAN_AUTH_LOG - what's it all about? =
49
-
50
- 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`:
51
-
52
- define('WP_FAIL2BAN_AUTH_LOG',LOG_AUTHPRIV);
53
-
54
- = WP_FAIL2BAN_LOG_PINGBACKS - what's it all about? =
55
-
56
- Based on a suggestion from *maghe*, *WPf2b* can now log pingbacks. To enable this feature, add the following to `wp-config.php`:
57
-
58
- define('WP_FAIL2BAN_LOG_PINGBACKS',true);
59
-
60
- By default, *WPf2b* uses LOG_USER for logging pingbacks. If you'd rather it used a different facility you can change it by adding something like the following to `wp-config.php`:
61
-
62
- define('WP_FAIL2BAN_PINGBACK_LOG',LOG_LOCAL3);
63
-
64
- = WP_FAIL2BAN_BLOCK_USER_ENUMERATION - what's it all about? =
65
-
66
- Brute-forcing WP requires knowing a valid username. Unfortunately, WP makes this all but trivial.
67
-
68
- Based on a suggestion from *geeklol* and a plugin by *ROIBOT*, *WPf2b* can now block user enumeration attempts. Just add the following to `wp-config.php`:
69
-
70
- define('WP_FAIL2BAN_BLOCK_USER_ENUMERATION',true);
71
-
72
- = WP_FAIL2BAN_PROXIES - what's it all about? =
73
-
74
- The idea here is to list the IP addresses of the trusted proxies that will appear as the remote IP for the request. When defined:
75
-
76
- * If the remote address appears in the `WP_FAIL2BAN_PROXIES` list, *WPf2b* will log the IP address from the `X-Forwarded-For` header
77
- * If the remote address does not appear in the `WP_FAIL2BAN_PROXIES` list, *WPf2b* will return a 403 error
78
- * If there's no X-Forwarded-For header, *WPf2b* will behave as if `WP_FAIL2BAN_PROXIES` isn't defined
79
-
80
- To set `WP_FAIL2BAN_PROXIES`, add something like the following to `wp-config.php`:
81
-
82
- define('WP_FAIL2BAN_PROXIES','192.168.0.42,192.168.42.0/24');
83
-
84
- *WPf2b* doesn't do anything clever with the list - beware of typos!
85
-
86
- = WP_FAIL2BAN_BLOCKED_USERS - what's it all about? =
87
-
88
  The bots that try to brute-force WordPress logins aren't that clever (no doubt that will change), but they may only make one request per IP every few hours in an attempt to avoid things like `fail2ban`. With large botnets this can still create significant load.
89
 
90
  Based on a suggestion from *jmadea*, *WPf2b* now allows you to specify a regex that will shortcut the login process if the requested username matches.
@@ -95,69 +88,121 @@ For example, putting the following in `wp-config.php`:
95
 
96
  will block any attempt to log in as `admin` before most of the core WordPress code is run. Unless you go crazy with it, a regex is usually cheaper than a call to the database so this should help keep things running during an attack.
97
 
98
- *WPf2b* doesn't do anything to the regex other than make it case-insensitive.
99
-
100
- == Changelog ==
101
-
102
- = 2.3.2 =
103
- * Bugfix `WP_FAIL2BAN_BLOCKED_USERS`.
104
-
105
- = 2.3.0 =
106
- * Bugfix in *experimental* `WP_FAIL2BAN_PROXIES` code (thanks to KyleCartmell).
107
-
108
- = 2.2.1 =
109
- * Fix stupid mistake with WP_FAIL2BAN_BLOCKED_USERS.
110
-
111
- = 2.2.0 =
112
- * Custom authentication log is now called WP_FAIL2BAN_AUTH_LOG
113
- * Add logging for pingbacks
114
- * Custom pingback log is called WP_FAIL2BAN_PINGBACK_LOG
115
-
116
- = 2.1.1 =
117
- * Minor bugfix.
118
-
119
- = 2.1.0 =
120
- * Add support for blocking user enumeration; see `WP_FAIL2BAN_BLOCK_USER_ENUMERATION`
121
- * Add support for CIDR notation in `WP_FAIL2BAN_PROXIES`.
122
 
123
- = 2.0.1 =
124
- * Bugfix in *experimental* `WP_FAIL2BAN_PROXIES` code.
 
125
 
126
- = 2.0.0 =
127
- * Add *experimental* support for X-Forwarded-For header; see `WP_FAIL2BAN_PROXIES`
128
- * Add *experimental* support for regex-based login blocking; see `WP_FAIL2BAN_BLOCKED_USERS`
129
 
130
- = 1.2.1 =
131
- * Update FAQ.
132
 
133
- = 1.2 =
134
- * Fix harmless warning.
 
 
 
135
 
136
- = 1.1 =
137
- * Minor cosmetic updates.
138
 
139
- = 1.0 =
140
- * Initial release.
 
 
 
141
 
142
- == Upgrade Notice ==
143
 
144
- = 2.3.0 =
145
- Fix for WP_FAIL2BAN_PROXIES; if you're not using it you can safely skip this release.
146
 
147
- = 2.2.1 =
148
- Bugfix.
 
 
 
149
 
150
- = 2.2.0 =
151
- BREAKING CHANGE: WP_FAIL2BAN_LOG has been renamed to WP_FAIL2BAN_AUTH_LOG
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
 
153
  Pingbacks are getting a lot of attention recently, so *WPf2b* can now log them.
154
- The `wordpress.conf` filter has been updated; you will need to update your `fail2ban` configuration.
155
-
156
- = 2.1.0 =
157
- The `wordpress.conf` filter has been updated; you will need to update your `fail2ban` configuration.
158
-
159
- = 2.0.1 =
160
- Bugfix in experimental code; still an experimental release.
161
-
162
- = 2.0.0 =
163
- 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://charles.lecklider.org/wordpress/wp-fail2ban/
5
+ Tags: fail2ban, login, security, syslog
6
+ Requires at least: 3.4.0
7
+ Tested up to: 4.4.2
8
+ Stable tag: 3.0.0
9
+ License: GPLv2 or later
10
+ License URI: http://www.gnu.org/licenses/gpl-2.0.html
11
+
12
+ Write all login attempts to syslog for integration with fail2ban.
13
+
14
+ == Description ==
15
+
16
  [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.
17
 
18
  *WP fail2ban* logs all login attempts, whether successful or not, to syslog using LOG_AUTH. To make log parsing as simple as possible *WPf2b* uses the same format as sshd. For example:
19
 
20
+ Oct 17 20:59:54 foobar wordpress(www.example.com)[1234]: Authentication failure for admin from 192.168.0.1
21
+ Oct 17 21:00:00 foobar wordpress(www.example.com)[2345]: Accepted password for admin from 192.168.0.1
22
+
23
+ *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.
24
+
25
+ Requires PHP 5.3 or later.
26
+
27
+ = Other Features =
28
+
29
+ **CloudFlare and Proxy Servers**
30
+
31
+ *WPf2b* can be configured to work with CloudFlare and other proxy servers. See `WP_FAIL2BAN_PROXIES` in the FAQ.
32
+
33
+ **Pingbacks**
34
+
35
+ *WPf2b* can log all pingbacks. See `WP_FAIL2BAN_LOG_PINGBACKS` in the FAQ.
36
+
37
+ **WP_FAIL2BAN_BLOCK_USER_ENUMERATION**
38
+
39
+ *WPf2b* can block user enumeration. See `WP_FAIL2BAN_BLOCK_USER_ENUMERATION` in the FAQ.
40
+
41
+ **Work-Arounds for Broken syslogd**
42
+
43
+ *WPf2b* can be configured to work around most syslogd weirdness. See `WP_FAIL2BAN_SYSLOG_SHORT_TAG` and `WP_FAIL2BAN_HTTP_HOST` in the FAQ.
44
+
45
+ **Blocking Users**
46
+
47
+ *WPf2b* can be configured to short-cut the login process when the username matches a regex. See `WP_FAIL2BAN_BLOCKED_USERS` in the FAQ.
48
+
49
+
50
+
51
+ == Installation ==
52
+
53
  1. Upload the plugin to your plugins directory
54
  1. Activate the plugin through the 'Plugins' menu in WordPress
55
  1. Copy `wordpress.conf` to your `fail2ban/filters.d` directory
56
  1. Edit `jail.local` to include something like:
57
+ ~~~
58
+ [wordpress]
59
+ enabled = true
60
+ filter = wordpress
61
+ logpath = /var/log/auth.log
62
+ ~~~
63
+ 5. Reload or restart `fail2ban`
64
+
65
+ You may want to set `WP_FAIL2BAN_BLOCK_USER_ENUMERATION`, `WP_FAIL2BAN_PROXIES` and/or `WP_FAIL2BAN_BLOCKED_USERS`; see the FAQ for details.
66
+
67
+ == Frequently Asked Questions ==
68
+
69
+ = WP_FAIL2BAN_SYSLOG_SHORT_TAG – what’s it for? =
70
+
71
+ Some flavours of Linux come with a `syslogd` that can't cope with the normal message format *WPf2b* uses; basically, they assume that the first part of the message (the tag) won't exceed some (small) number of characters, and mangle the message if it does. This breaks the regex in the *fail2ban* filter and so nothing gets blocked.
72
+
73
+ Adding:
74
+
75
+ define('WP_FAIL2BAN_SYSLOG_SHORT_TAG',true);
76
+
77
+ to `functions.php` will make *WPf2b* use `wp` as the syslog tag, rather than the normal `wordpress`. This buys you 7 characters which may be enough to work around the problem, but if it's not enough you should look at `WP_FAIL2BAN_HTTP_HOST` too.
78
+
79
+ = WP_FAIL2BAN_BLOCKED_USERS – what’s it all about? =
80
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  The bots that try to brute-force WordPress logins aren't that clever (no doubt that will change), but they may only make one request per IP every few hours in an attempt to avoid things like `fail2ban`. With large botnets this can still create significant load.
82
 
83
  Based on a suggestion from *jmadea*, *WPf2b* now allows you to specify a regex that will shortcut the login process if the requested username matches.
88
 
89
  will block any attempt to log in as `admin` before most of the core WordPress code is run. Unless you go crazy with it, a regex is usually cheaper than a call to the database so this should help keep things running during an attack.
90
 
91
+ *WPf2b* doesn't do anything to the regex other than make it case-insensitive.
92
+
93
+ = WP_FAIL2BAN_PROXIES – what’s it all about? =
94
+
95
+ The idea here is to list the IP addresses of the trusted proxies that will appear as the remote IP for the request. When defined:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
+ * If the remote address appears in the `WP_FAIL2BAN_PROXIES` list, *WPf2b* will log the IP address from the `X-Forwarded-For` header
98
+ * If the remote address does not appear in the `WP_FAIL2BAN_PROXIES` list, *WPf2b* will return a 403 error
99
+ * If there's no X-Forwarded-For header, *WPf2b* will behave as if `WP_FAIL2BAN_PROXIES` isn't defined
100
 
101
+ To set `WP_FAIL2BAN_PROXIES`, add something like the following to `wp-config.php`:
 
 
102
 
103
+ define('WP_FAIL2BAN_PROXIES','192.168.0.42,192.168.42.0/24');
 
104
 
105
+ *WPf2b* doesn't do anything clever with the list - beware of typos!
106
+
107
+ = WP_FAIL2BAN_BLOCK_USER_ENUMERATION – what’s it all about? =
108
+
109
+ Brute-forcing WP requires knowing a valid username. Unfortunately, WP makes this all but trivial.
110
 
111
+ Based on a suggestion from *geeklol* and a plugin by *ROIBOT*, *WPf2b* can now block user enumeration attempts. Just add the following to `wp-config.php`:
 
112
 
113
+ define('WP_FAIL2BAN_BLOCK_USER_ENUMERATION',true);
114
+
115
+ = WP_FAIL2BAN_LOG_PINGBACKS – what’s it all about? =
116
+
117
+ Based on a suggestion from *maghe*, *WPf2b* can now log pingbacks. To enable this feature, add the following to `wp-config.php`:
118
 
119
+ define('WP_FAIL2BAN_LOG_PINGBACKS',true);
120
 
121
+ By default, *WPf2b* uses LOG_USER for logging pingbacks. If you'd rather it used a different facility you can change it by adding something like the following to `wp-config.php`:
 
122
 
123
+ define('WP_FAIL2BAN_PINGBACK_LOG',LOG_LOCAL3);
124
+
125
+ = WP_FAIL2BAN_AUTH_LOG – what’s it all about? =
126
+
127
+ 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`:
128
 
129
+ define('WP_FAIL2BAN_AUTH_LOG',LOG_AUTHPRIV);
130
+
131
+ = Why is fail2ban complaining on my flavour of Linux? =
132
+
133
+ Depending on your `fail2ban` configuration, you may need to add a line like:
134
+
135
+ port = http,https
136
+
137
+ to the `[wordpress]` section in `jail.local`.
138
+
139
+ == Changelog ==
140
+
141
+ = 3.0.0 =
142
+ * Add `WP_FAIL2BAN_SYSLOG_SHORT_TAG`.
143
+ * Add `WP_FAIL2BAN_HTTP_HOST`.
144
+ * Log XML-RPC authentication failure.
145
+ * Add better support for MU deployment.
146
+
147
+ = 2.3.2 =
148
+ * Bugfix `WP_FAIL2BAN_BLOCKED_USERS`.
149
+
150
+ = 2.3.0 =
151
+ * Bugfix in *experimental* `WP_FAIL2BAN_PROXIES` code (thanks to KyleCartmell).
152
+
153
+ = 2.2.1 =
154
+ * Fix stupid mistake with `WP_FAIL2BAN_BLOCKED_USERS`.
155
+
156
+ = 2.2.0 =
157
+ * Custom authentication log is now called `WP_FAIL2BAN_AUTH_LOG`
158
+ * Add logging for pingbacks
159
+ * Custom pingback log is called `WP_FAIL2BAN_PINGBACK_LOG`
160
+
161
+ = 2.1.1 =
162
+ * Minor bugfix.
163
+
164
+ = 2.1.0 =
165
+ * Add support for blocking user enumeration; see `WP_FAIL2BAN_BLOCK_USER_ENUMERATION`
166
+ * Add support for CIDR notation in `WP_FAIL2BAN_PROXIES`.
167
+
168
+ = 2.0.1 =
169
+ * Bugfix in *experimental* `WP_FAIL2BAN_PROXIES` code.
170
+
171
+ = 2.0.0 =
172
+ * Add *experimental* support for X-Forwarded-For header; see `WP_FAIL2BAN_PROXIES`
173
+ * Add *experimental* support for regex-based login blocking; see `WP_FAIL2BAN_BLOCKED_USERS`
174
+
175
+ = 1.2.1 =
176
+ * Update FAQ.
177
+
178
+ = 1.2 =
179
+ * Fix harmless warning.
180
+
181
+ = 1.1 =
182
+ * Minor cosmetic updates.
183
+
184
+ = 1.0 =
185
+ * Initial release.
186
+
187
+ == Upgrade Notice ==
188
+
189
+ = 2.3.0 =
190
+ Fix for `WP_FAIL2BAN_PROXIES`; if you're not using it you can safely skip this release.
191
+
192
+ = 2.2.1 =
193
+ Bugfix.
194
+
195
+ = 2.2.0 =
196
+ BREAKING CHANGE: `WP_FAIL2BAN_LOG` has been renamed to `WP_FAIL2BAN_AUTH_LOG`
197
 
198
  Pingbacks are getting a lot of attention recently, so *WPf2b* can now log them.
199
+ The `wordpress.conf` filter has been updated; you will need to update your `fail2ban` configuration.
200
+
201
+ = 2.1.0 =
202
+ The `wordpress.conf` filter has been updated; you will need to update your `fail2ban` configuration.
203
+
204
+ = 2.0.1 =
205
+ Bugfix in experimental code; still an experimental release.
206
+
207
+ = 2.0.0 =
208
+ 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.
wordpress.conf → wordpress-hard.conf RENAMED
@@ -12,7 +12,7 @@ before = common.conf
12
 
13
  [Definition]
14
 
15
- _daemon = wordpress
16
 
17
  # Option: failregex
18
  # Notes.: regex to match the password failures messages in the logfile. The
@@ -21,14 +21,13 @@ _daemon = wordpress
21
  # (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
22
  # Values: TEXT
23
  #
24
- failregex = ^%(__prefix_line)sAuthentication failure for .* from <HOST>$
25
  ^%(__prefix_line)sBlocked authentication attempt for .* from <HOST>$
26
  ^%(__prefix_line)sBlocked user enumeration attempt from <HOST>$
27
- ^%(__prefix_line)sPingback requested from <HOST>$
28
 
29
  # Option: ignoreregex
30
  # Notes.: regex to ignore. If this regex matches, the line is ignored.
31
  # Values: TEXT
32
  #
33
  ignoreregex =
34
-
12
 
13
  [Definition]
14
 
15
+ _daemon = (?:wordpress|wp)
16
 
17
  # Option: failregex
18
  # Notes.: regex to match the password failures messages in the logfile. The
21
  # (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
22
  # Values: TEXT
23
  #
24
+ failregex = ^%(__prefix_line)sAuthentication attempt for unknown user from <HOST>$
25
  ^%(__prefix_line)sBlocked authentication attempt for .* from <HOST>$
26
  ^%(__prefix_line)sBlocked user enumeration attempt from <HOST>$
27
+ ^%(__prefix_line)sPingback error .* generated from <HOST>$
28
 
29
  # Option: ignoreregex
30
  # Notes.: regex to ignore. If this regex matches, the line is ignored.
31
  # Values: TEXT
32
  #
33
  ignoreregex =
 
wordpress-soft.conf ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Fail2Ban configuration file
2
+ #
3
+ # Author: Charles Lecklider
4
+ #
5
+
6
+ [INCLUDES]
7
+
8
+ # Read common prefixes. If any customizations available -- read them from
9
+ # common.local
10
+ before = common.conf
11
+
12
+
13
+ [Definition]
14
+
15
+ _daemon = (?:wordpress|wp)
16
+
17
+ # Option: failregex
18
+ # Notes.: regex to match the password failures messages in the logfile. The
19
+ # host must be matched by a group named "host". The tag "<HOST>" can
20
+ # be used for standard IP/hostname matching and is only an alias for
21
+ # (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
22
+ # Values: TEXT
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 =
wp-fail2ban.php CHANGED
@@ -1,121 +1,170 @@
1
- <?php
2
- /**
3
- * Plugin Name: WP fail2ban
4
- * Plugin URI: https://charles.lecklider.org/wordpress/wp-fail2ban/
5
- * Description: Write all login attempts to syslog for integration with fail2ban.
6
- * Version: 2.3.1
7
- * Author: Charles Lecklider
8
- * Author URI: https://charles.lecklider.org/
9
- * License: GPL2
10
- * SPDX-License-Identifier: GPL-2.0
11
- */
12
-
13
- /**
14
- * Copyright 2012-15 Charles Lecklider (email : wordpress@charles.lecklider.org)
15
- *
16
- * This program is free software; you can redistribute it and/or modify
17
- * it under the terms of the GNU General Public License, version 2, as
18
- * published by the Free Software Foundation.
19
- *
20
- * This program is distributed in the hope that it will be useful,
21
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
- * GNU General Public License for more details.
24
- *
25
- * You should have received a copy of the GNU General Public License
26
- * along with this program; if not, write to the Free Software
27
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28
- */
29
-
30
- namespace org\lecklider\charles\wordpress\wp_fail2ban;
31
-
32
-
33
- function openlog($log = LOG_AUTH, $custom_log = 'WP_FAIL2BAN_AUTH_LOG')
34
- {
35
- \openlog('wordpress('.$_SERVER['HTTP_HOST'].')',
36
- LOG_NDELAY|LOG_PID,
37
- defined($custom_log) ? constant($custom_log) : $log);
38
- }
39
-
40
- function bail()
41
- {
42
- ob_end_clean();
43
- header('HTTP/1.0 403 Forbidden');
44
- header('Content-Type: text/plain');
45
- exit('Forbidden');
46
- }
47
-
48
- function remote_addr()
49
- {
50
- if (defined('WP_FAIL2BAN_PROXIES')) {
51
- if (array_key_exists('HTTP_X_FORWARDED_FOR',$_SERVER)) {
52
- $ip = ip2long($_SERVER['REMOTE_ADDR']);
53
- foreach(explode(',',WP_FAIL2BAN_PROXIES) as $proxy) {
54
- if (2 == count($cidr = explode('/',$proxy))) {
55
- $net = ip2long($cidr[0]);
56
- $mask = ~ ( pow(2, (32 - $cidr[1])) - 1 );
57
- } else {
58
- $net = ip2long($proxy);
59
- $mask = -1;
60
- }
61
- if ($net == ($ip & $mask)) {
62
- return (false===($len = strpos($_SERVER['HTTP_X_FORWARDED_FOR'],',')))
63
- ? $_SERVER['HTTP_X_FORWARDED_FOR']
64
- : substr($_SERVER['HTTP_X_FORWARDED_FOR'],0,$len);
65
- }
66
- }
67
- }
68
- }
69
-
70
- return $_SERVER['REMOTE_ADDR'];
71
- }
72
-
73
- if (defined('WP_FAIL2BAN_BLOCKED_USERS')) {
74
- add_filter( 'authenticate',
75
- function($user, $username, $password)
76
- {
77
- if (!empty($username) && preg_match('/'.WP_FAIL2BAN_BLOCKED_USERS.'/i', $username)) {
78
- openlog();
79
- \syslog(LOG_NOTICE,"Blocked authentication attempt for $username from ".remote_addr());
80
- bail();
81
- }
82
-
83
- return $user;
84
- },1,3);
85
- }
86
- if (defined('WP_FAIL2BAN_BLOCK_USER_ENUMERATION') && true === WP_FAIL2BAN_BLOCK_USER_ENUMERATION) {
87
- add_filter( 'redirect_canonical',
88
- function($redirect_url, $requested_url)
89
- {
90
- if (intval(@$_GET['author'])) {
91
- openlog();
92
- \syslog(LOG_NOTICE,'Blocked user enumeration attempt from '.remote_addr());
93
- bail();
94
- }
95
-
96
- return $redirect_url;
97
- },10,2);
98
- }
99
- add_action( 'wp_login',
100
- function($user_login, $user)
101
- {
102
- openlog();
103
- \syslog(LOG_INFO,"Accepted password for $user_login from ".remote_addr());
104
- },10,2);
105
- add_action( 'wp_login_failed',
106
- function($username)
107
- {
108
- openlog();
109
- \syslog(LOG_NOTICE,"Authentication failure for $username from ".remote_addr());
110
- });
111
- if (defined('WP_FAIL2BAN_LOG_PINGBACKS') && true === WP_FAIL2BAN_LOG_PINGBACKS) {
112
- add_action( 'xmlrpc_call',
113
- function($call)
114
- {
115
- if ('pingback.ping' == $call) {
116
- openlog(LOG_USER,'WP_FAIL2BAN_PINGBACK_LOG');
117
- \syslog(LOG_INFO,"Pingback requested from ".remote_addr());
118
- }
119
- });
120
- }
121
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin Name: WP fail2ban
4
+ * Plugin URI: https://charles.lecklider.org/wordpress/wp-fail2ban/
5
+ * Description: Write all login attempts to syslog for integration with fail2ban.
6
+ * Text Domain: wp-fail2ban
7
+ * Version: 3.0.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-16 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
19
+ * published by the Free Software Foundation.
20
+ *
21
+ * This program is distributed in the hope that it will be useful,
22
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
+ * GNU General Public License for more details.
25
+ *
26
+ * You should have received a copy of the GNU General Public License
27
+ * along with this program; if not, write to the Free Software
28
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29
+ */
30
+
31
+ namespace org\lecklider\charles\wordpress\wp_fail2ban;
32
+
33
+
34
+ if (!defined('WP_FAIL2BAN')) {
35
+ define('WP_FAIL2BAN', true);
36
+
37
+ function openlog($log = LOG_AUTH, $custom_log = 'WP_FAIL2BAN_AUTH_LOG')
38
+ {
39
+ $tag = (defined('WP_FAIL2BAN_SYSLOG_SHORT_TAG') && true === WP_FAIL2BAN_SYSLOG_SHORT_TAG)
40
+ ? 'wp'
41
+ : 'wordpress';
42
+ $host = (array_key_exists('WP_FAIL2BAN_HTTP_HOST',$_ENV))
43
+ ? $_ENV['WP_FAIL2BAN_HTTP_HOST']
44
+ : $_SERVER['HTTP_HOST'];
45
+ \openlog("$tag($host)",
46
+ LOG_NDELAY|LOG_PID,
47
+ defined($custom_log) ? constant($custom_log) : $log);
48
+ }
49
+
50
+ function bail()
51
+ {
52
+ ob_end_clean();
53
+ header('HTTP/1.0 403 Forbidden');
54
+ header('Content-Type: text/plain');
55
+ exit('Forbidden');
56
+ }
57
+
58
+ function remote_addr()
59
+ {
60
+ if (defined('WP_FAIL2BAN_PROXIES')) {
61
+ if (array_key_exists('HTTP_X_FORWARDED_FOR',$_SERVER)) {
62
+ $ip = ip2long($_SERVER['REMOTE_ADDR']);
63
+ foreach(explode(',',WP_FAIL2BAN_PROXIES) as $proxy) {
64
+ if (2 == count($cidr = explode('/',$proxy))) {
65
+ $net = ip2long($cidr[0]);
66
+ $mask = ~ ( pow(2, (32 - $cidr[1])) - 1 );
67
+ } else {
68
+ $net = ip2long($proxy);
69
+ $mask = -1;
70
+ }
71
+ if ($net == ($ip & $mask)) {
72
+ return (false===($len = strpos($_SERVER['HTTP_X_FORWARDED_FOR'],',')))
73
+ ? $_SERVER['HTTP_X_FORWARDED_FOR']
74
+ : substr($_SERVER['HTTP_X_FORWARDED_FOR'],0,$len);
75
+ }
76
+ }
77
+ }
78
+ }
79
+
80
+ return $_SERVER['REMOTE_ADDR'];
81
+ }
82
+ /*
83
+ * @since 2.0.0
84
+ */
85
+ if (defined('WP_FAIL2BAN_BLOCKED_USERS')) {
86
+ add_filter( 'authenticate',
87
+ function($user, $username, $password)
88
+ {
89
+ if (!empty($username) && preg_match('/'.WP_FAIL2BAN_BLOCKED_USERS.'/i', $username)) {
90
+ openlog();
91
+ \syslog(LOG_NOTICE,"Blocked authentication attempt for $username from ".remote_addr());
92
+ bail();
93
+ }
94
+
95
+ return $user;
96
+ },1,3);
97
+ }
98
+ /*
99
+ * @since 2.1.0
100
+ */
101
+ if (defined('WP_FAIL2BAN_BLOCK_USER_ENUMERATION') && true === WP_FAIL2BAN_BLOCK_USER_ENUMERATION) {
102
+ add_filter( 'redirect_canonical',
103
+ function($redirect_url, $requested_url)
104
+ {
105
+ if (intval(@$_GET['author'])) {
106
+ openlog();
107
+ \syslog(LOG_NOTICE,'Blocked user enumeration attempt from '.remote_addr());
108
+ bail();
109
+ }
110
+
111
+ return $redirect_url;
112
+ },10,2);
113
+ }
114
+ /*
115
+ * @since 2.2.0
116
+ */
117
+ if (defined('WP_FAIL2BAN_LOG_PINGBACKS') && true === WP_FAIL2BAN_LOG_PINGBACKS) {
118
+ add_action( 'xmlrpc_call',
119
+ function($call)
120
+ {
121
+ if ('pingback.ping' == $call) {
122
+ openlog(LOG_USER,'WP_FAIL2BAN_PINGBACK_LOG');
123
+ \syslog(LOG_INFO,'Pingback requested from '.remote_addr());
124
+ }
125
+ });
126
+ }
127
+ /*
128
+ * @since 1.0.0
129
+ */
130
+ add_action( 'wp_login',
131
+ function($user_login, $user)
132
+ {
133
+ openlog();
134
+ \syslog(LOG_INFO,"Accepted password for $user_login from ".remote_addr());
135
+ },10,2);
136
+ /*
137
+ * @since 1.0.0
138
+ */
139
+ add_action( 'wp_login_failed',
140
+ function($username)
141
+ {
142
+ $msg = (wp_cache_get($username, 'userlogins'))
143
+ ? "Authentication failure for $username from "
144
+ : "Authentication attempt for unknown user $username from ";
145
+ openlog();
146
+ \syslog(LOG_NOTICE,$msg.remote_addr());
147
+ });
148
+ /*
149
+ * @since 3.0.0
150
+ */
151
+ add_action( 'xmlrpc_login_error',
152
+ function($error, $user)
153
+ {
154
+ openlog();
155
+ \syslog(LOG_NOTICE,'XML-RPC authentication failure from '.remote_addr());
156
+ bail();
157
+ },10,2);
158
+ /*
159
+ * @since 3.0.0
160
+ */
161
+ add_filter( 'xmlrpc_pingback_error',
162
+ function($ixr_error)
163
+ {
164
+ if ( $ixr_error->code === 48 )
165
+ return $ixr_error;
166
+ openlog();
167
+ \syslog(LOG_NOTICE,'Pingback error '.$ixr_error->code.' generated from '.remote_addr());
168
+ },5);
169
+ }
170
+