A WordPress plugin that helps keeping WordPress websites secure.
BC Security is not available at WordPress Plugins Directory, but there are several other ways you can get it.
If you have WP-CLI installed, you can install (and optionally activate) BC Security with a single command:
wp plugin install [--activate] https://github.com/chesio/bc-security/archive/master.zip
Composer is a great tool for managing PHP project dependencies. Although WordPress itself does not make it easy to use Composer to manage WordPress installation as a whole, there are multiple ways how to do it.
BC Security is available at Packagist, so just run composer require chesio/bc-security
as usual.
Master branch always contains latest stable version, so you can install BC Security by cloning it from within your plugins directory:
cd [your-project]/wp-content/plugins
git clone --single-branch --branch master https://github.com/chesio/bc-security.git
Updating is as easy as:
cd [your-project]/wp-content/plugins/bc-security
git pull
BC Security can be installed and updated via Git Updater plugin.
This method is the least recommended, but it works without any other tool. You can download BC Security directly from GitHub. Make sure to unpack the plugin into correct directory and drop the version number from folder name.
Several features of BC Security depends on the knowledge of remote IP address, so it is important that you let the plugin know how your server is connected to the Internet. You can either set connection type via Setup page or with BC_SECURITY_CONNECTION_TYPE
constant.
You may also optionally provide Google API key if you want to check your website against the Google Safe Browsing lists of unsafe web resources. The key must have Google Safe Browsing API enabled. As with the connection type, you can configure the key either via Setup page or with BC_SECURITY_GOOGLE_API_KEY
constant.
Note: If you already have an installation with BC Security set up and would like to set up another installation in the same way, you can export plugin settings (including connection type) from the former installation and import them to the latter.
BC Security can help you find potential security issues or even signs of breach.
Since security measures for development installations do not have to be as strict as for live installations, some checks are run only in live environment. A live environment is determined as one where wp_get_environment_type()
returns either production
or staging
, but there is a dedicated filter that can be used to override live environment detection.
Basic checks cover common security practices. They do not require any information from third party sources to proceed and thus do not leak any information about your website:
WP_DEBUG
and WP_DEBUG_LOG
constants are set to true.Advanced checks require data from external sources, therefore they leak some information about your website and take more time to execute.
In the moment, list of installed plugins (but only those with readme.md or readme.txt file) is shared with WordPress.org and site URL is shared with Google.
WordPress core files verification is done in two phases:
The check uses the same checksums API as core verify-checksums
command from WP-CLI.
Plugin files verification works only for plugins installed from Plugins Directory. The verification process is akin to the core files verification, although the API is slightly different (see related Trac ticket and specification).
Important: any plugins under version control (Git or Subversion) are automatically omitted from the check.
Although plugins can be removed from Plugins Directory for several reasons (not only because they have security vulnerability), use of removed plugins is discouraged. Obviously, this check also works only for plugins installed from Plugins Directory.
Checks whether your website is included on any of Google's lists of unsafe web resources - this is usually a solid indicator of compromise. Note that for this check to run you have to provide properly configured API key via plugin setup. This check is only run in live environment.
Both basic and advanced checks can be run manually from a dedicated page in backend, but can be also configured to run periodically (once a day) in the background. Basic checks are run via a single cron job, while each of advanced checks is run via a separate cron job.
BC Security allows you to:
Passwords are checked on user login. If password is present in the Pwned Passwords database, a non-dismissible warning is displayed in backend encouraging the user to change its password. By default, the warning is displayed on all pages, but this can be customized via a filter.
Passwords are validated on user creation, password change or password reset. If password is present in the Pwned Passwords database, the operation is aborted with an error message asking user to pick a different password.
Remote IP addresses that are scanning your website for weaknesses can be automatically blocked for configured amount of time. Such scanners can be usually quite easily detected because while scanning a website they trigger a lot of 404 errors and URLs they try to access differ from "valid" 404 errors: usually they try to find a known vulnerable plugin, forgotten backup file or PHP script used for administrative purposes.
There are five built-in rules available (they are not active by default):
.asp
or .aspx
).php
).tgz
or .zip
)backup
in basename or with .back
, .old
or .tmp
extension)readme.txt
file is accessedYou may define custom rules as well (in form of regular expression).
Important: When using this feature it is strongly recommended to activate synchronization of internal blocklist with .htaccess
file!
BC Security maintains a list of IP addresses with limited access to the website. This list is automatically populated by Login security and Bad requests banner modules, but manual addition of IP addresses is also possible.
Out-dated records are automatically removed from the list by WP-Cron job scheduled to run every night. The job can be deactivated in backend, if desired.
On Apache webserver in version 2.3 or newer, block rules with "website" access scope can be automatically synchronized with .htaccess
file. This makes access blocking much more powerful as all requests to the webserver are blocked this way and not only the ones handled by WordPress.
This feature must be however set up manually - following two lines have to be added at the top of root .htaccess
file in order for it to work:
# BEGIN BC Security
# END BC Security
After you have completed the setup, either wait for automatic synchronization to kick in on next locking event or run manual synchronization from the administration page.
In addition to internal blocklist, BC Security can be configured to fetch list of IP addresses to block from external sources. Currently only Amazon AWS IP ranges can be used this way.
As with internal blocklist, external blocklist can be used to limit access to entire website or login process only.
BC Security allows to send automatic email notification to configured recipients on following occasions:
Note: Known IP address is an IP address from which a successful login attempt had been previously made. Information about successful login attempts is fetched from event logs.
You can mute all email notifications by setting constant BC_SECURITY_MUTE_NOTIFICATIONS
to true
via define('BC_SECURITY_MUTE_NOTIFICATIONS', true);
. If you run a website in multiple environments (development, staging, production etc.), you may find it disturbing to receive email notifications from development or any environment other than production. Declaring the constant for particular environment only is very easy, if you use a multi-environment setup.
Following events triggered by BC Security are logged:
(*) Note: in case internal blocklist is synchronized with .htaccess
file, HTTP requests are blocked by webserver before being handled to WordPress, therefore they cannot be logged by the plugin.
Following events triggered by WordPress core are logged:
Logs are stored in database and can be viewed on backend. Logs are automatically deleted based on their age and overall size: by default no more than 20 thousands of records are kept and any log records older than 365 days are removed, but these limits can be configured.
Some of the modules listed above come with settings panel. Further customization can be done with filters provided by plugin:
bc-security/filter:is-admin
- filters boolean value that determines whether current user is considered an admin user. This check determines whether admin login notification should be sent for particular user. By default, any user with manage_options
capability is considered an admin (or manage_network
on multisite).bc-security/filter:is-live
- filters boolean value that determines whether your website is running in a live environment.bc-security/filter:plugin-changelog-url
- filters changelog URL of given plugin. Might come handy in case of plugins not hosted in Plugins Directory.bc-security/filter:obvious-usernames
- filters array of common usernames that are being checked via checklist check. By default, the array consists of admin and administrator values.bc-security/filter:plugins-to-check-for-integrity
- filters array of plugins that should have their integrity checked. By default, the array consists of all installed plugins that have _readme.md__ or readme.txt file. Note that plugins under version control are automatically omitted.bc-security/filter:plugins-to-check-for-removal
- filters array of plugins to check for their presence in WordPress.org Plugins Directory. By default, the array consists of all installed plugins that have _readme.md__ or readme.txt file.bc-security/filter:modified-files-ignored-in-core-integrity-check
- filters array of files that should not be reported as modified in checksum verification of core WordPress files. By default, the array consist of wp-config-sample.php and wp-includes/version.php values.bc-security/filter:unknown-files-ignored-in-core-integrity-check
- filters array of files that should not be reported as unknown in checksum verification of core WordPress files. By default, the array consist of .htaccess, wp-config.php, liesmich.html, olvasdel.html and procitajme.html values.bc-security/filter:show-pwned-password-warning
- filters whether the "pwned password" warning should be displayed for current user on current screen.bc-security/filter:internal-blocklist-default-manual-lock-duration
- filters number of seconds that is used as default value in lock duration field of manual internal blocklisting form. By default, the value is equal to one month in seconds.bc-security/filter:is-ip-address-locked
- filters boolean value that determines whether given IP address is currently on internal blocklist (within given scope).bc-security/filter:is-ip-address-blocked
- filters boolean value that determines whether given IP address is currently blocked either by external or internal blocklist (within given scope).bc-security/filter:log-404-event
- filters boolean value that determines whether current HTTP request that resulted in 404 response should be logged or not. To completely disable logging of 404 events, you can attach __return_false
function to the filter.bc-security/filter:events-with-hostname-resolution
- filters array of IDs of events for which hostname of involved IP address should be resolved via reverse DNS lookup. By default the following events are registered: attempts to authenticate with bad cookie, failed and successful login attempts and lockout events. Note that this functionality only relates to event logs report in backend - in case email notification is sent, hostname of reported IP address (if any) is always resolved separately.bc-security/filter:username-blacklist
- filters array of blacklisted usernames. Blacklisted usernames cannot be registered when opening new account and any login attempt using non-existing blacklisted username triggers long lockout. There are no default values, but the filter operates on usernames set via module settings, so it can be used to enforce blacklisting of particular usernames.