Skip to content

Commit

Permalink
Merge branch 'release-0.19.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
chesio committed Jun 2, 2022
2 parents fa4ba5d + 52e0a36 commit 96e2e29
Show file tree
Hide file tree
Showing 110 changed files with 1,591 additions and 783 deletions.
12 changes: 10 additions & 2 deletions .github/workflows/php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,30 @@ name: CI test suite
on:
pull_request:
paths:
- '.github/workflows/**'
- 'composer.*'
- phpcs.xml
- phpstan.neon
- '**.php'
push:
paths:
- '.github/workflows/**'
- 'composer.*'
- phpcs.xml
- phpstan.neon
- '**.php'

# Cancels all previous workflow runs for the same branch that have not yet completed.
concurrency:
# The concurrency group contains the workflow name and the branch name.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
strategy:
matrix:
php-versions: ['8.0', '7.4', '7.3']
php-versions: ['8.1', '8.0', '7.4', '7.3']

runs-on: ubuntu-latest

Expand All @@ -35,7 +43,7 @@ jobs:
run: composer validate

- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest --classmap-authoritative
uses: ramsey/composer-install@v1

- name: Run CI test suite
run: composer run-script ci
33 changes: 33 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# BC Security Changelog

## Upcoming version 0.19.0 (2022-06-02)

### Added

* PHP 8.1 is supported [#116](https://github.com/chesio/bc-security/issues/116).
* WordPress versions 5.9 and 6.0 are supported [#121](https://github.com/chesio/bc-security/issues/121) and [#127](https://github.com/chesio/bc-security/issues/127).
* An option to restrict login options has been implemented: login via email or login via username can be disabled [#123](https://github.com/chesio/bc-security/issues/123).
* [Changelog.md](CHANGELOG.md) has been added [#125](https://github.com/chesio/bc-security/issues/125).

### Removed

* "Check auth cookies" setting has been removed [#124](https://github.com/chesio/bc-security/issues/124).

## Version 0.18.1 (2021-12-29)

### Fixed

* EOL dates for PHP versions in PHP version check has been updated: EOL date for PHP 7.3 has been removed, EOL date for PHP 8.1 has been added [#115](https://github.com/chesio/bc-security/issues/115).

## Version 0.18.0 (2021-11-30)

### Added

* PHP 8.0 is supported [#104](https://github.com/chesio/bc-security/issues/104).
* Alert about "No removed plugins installed" has more information [#107](https://github.com/chesio/bc-security/issues/107).
* Detection of plugins installed from WordPress Directory has been improved [#112](https://github.com/chesio/bc-security/issues/112).
* On WordPress 5.8 and newer the plugin cannot be accidentally overriden from WordPress.org Plugins Directory [#111](https://github.com/chesio/bc-security/issues/111).

## Older releases

Notes on changes in all releases can be found [here](https://github.com/chesio/bc-security/releases).
45 changes: 23 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ Since security measures for development instalations do not have to be as strict
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:

1. Is backend editing of plugin and theme PHP files disabled?
1. Are directory listings disabled?
1. Is execution of PHP files from uploads directory forbidden?
1. Is display of PHP errors off by default? This check is only run in *live environment*.
1. Is error log file not publicly available? This check is only run if both `WP_DEBUG` and `WP_DEBUG_LOG` constants are set to true.
1. Are there no common usernames like admin or administrator on the system?
1. Are user passwords hashed with [more secure hashing algorithm](https://roots.io/improving-wordpress-password-security/) than MD5 used by [WordPress by default](https://core.trac.wordpress.org/ticket/21022)?
1. Is PHP version still supported?
2. Are directory listings disabled?
3. Is execution of PHP files from uploads directory forbidden?
4. Is display of PHP errors off by default? This check is only run in *live environment*.
5. Is error log file not publicly available? This check is only run if both `WP_DEBUG` and `WP_DEBUG_LOG` constants are set to true.
6. Are there no common usernames like admin or administrator on the system?
7. Are user passwords hashed with [more secure hashing algorithm](https://roots.io/improving-wordpress-password-security/) than MD5 used by [WordPress by default](https://core.trac.wordpress.org/ticket/21022)?
8. Is PHP version still supported?

#### Advanced checks

Expand All @@ -94,7 +94,7 @@ In the moment, list of installed plugins (but only those with _readme.txt_ file)

WordPress core files verification is done in two phases:
1. Official md5 checksums from WordPress.org are used to determine if any of core files have been modified.
1. All files in root directory, _wp-admin_ directory (including subdirectories) and _wp-includes_ directory (including subdirectories) are checked against official checksums list in order to find out any unknown files.
2. All files in root directory, _wp-admin_ directory (including subdirectories) and _wp-includes_ directory (including subdirectories) are checked against official checksums list in order to find out any unknown files.

The check uses the same checksums API as [`core verify-checksums`](https://developer.wordpress.org/cli/commands/core/verify-checksums/) command from [WP-CLI](https://wp-cli.org/).

Expand All @@ -120,10 +120,11 @@ Both basic and advanced checks can be run manually from a dedicated page in back

BC Security allows you to:
1. Disable pingbacks
1. Disable XML RPC methods that require authentication
1. Disable application passwords
1. Prevent usernames discovery via [REST API requests](https://developer.wordpress.org/rest-api/reference/users/) and [username enumeration](https://hackertarget.com/wordpress-user-enumeration/)
1. Check and/or validate user passwords using [Pwned Passwords](https://haveibeenpwned.com/Passwords) database and [API](https://haveibeenpwned.com/API/v2#PwnedPasswords)
2. Disable XML RPC methods that require authentication
3. Disable application passwords
4. Prevent usernames discovery via [REST API requests](https://developer.wordpress.org/rest-api/reference/users/) and [username eumeration](https://hackertarget.com/wordpress-user-enumeration/)
5. Disable login with email or login with username to reduce risk from brute-force or [credential stuffing attacks](https://owasp.org/www-community/attacks/Credential_stuffing).
6. Check and/or validate user passwords using [Pwned Passwords](https://haveibeenpwned.com/Passwords) database and [API](https://haveibeenpwned.com/API/v2#PwnedPasswords)

#### Passwords check

Expand All @@ -136,7 +137,7 @@ Passwords are validated on user creation, password change or password reset. If
### Login security

1. BC Security allows you to limit number of login attempts from single IP address. Implementation of this feature is heavily inspired by popular [Limit Login Attempts](https://wordpress.org/plugins/limit-login-attempts/) plugin with an extra feature of immediate blocking of specific usernames (like _admin_ or _administrator_).
1. BC Security offers an option to only display generic error message as a result of failed login attempt when wrong username, email or password is provided.
2. BC Security offers an option to only display generic error message as a result of failed login attempt when wrong username, email or password is provided.

### IP blacklist

Expand All @@ -149,12 +150,12 @@ Out-dated records are automatically removed from the list by WP-Cron job schedul
BC Security allows to send automatic email notification to configured recipients on following occasions:

1. WordPress update is available.
1. Plugin update is available.
1. Theme update is available.
1. User with administrator privileges has logged in.
1. Known IP address has been locked out (see note below).
1. [Checklist monitoring](#checklist-monitoring) triggers an alert. Note: there is one notification sent if any of basic checks fails, but separate notification is sent if any of advanced checks fails.
1. BC Security plugin has been deactivated.
2. Plugin update is available.
3. Theme update is available.
4. User with administrator privileges has logged in.
5. Known IP address has been locked out (see note below).
6. [Checklist monitoring](#checklist-monitoring) triggers an alert. Note: there is one notification sent if any of basic checks fails, but separate notification is sent if any of advanced checks fails.
7. BC Security plugin has been deactivated.

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](#events-logging).

Expand All @@ -165,8 +166,8 @@ You can mute all email notifications by setting constant `BC_SECURITY_MUTE_NOTIF
BC Security logs both short and long lockout events (see [Login Security](#login-security) feature). Also, the following events triggered by WordPress core are logged:

1. Attempts to authenticate with bad cookie
1. Failed and successful login attempts
1. Requests that result in 404 page
2. Failed and successful login attempts
3. Requests that result in 404 page

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.

Expand Down Expand Up @@ -202,4 +203,4 @@ Some of the modules listed above come with settings panel. Further customization
## Alternatives (and why I do not use them)

1. [Wordfence Security](https://wordpress.org/plugins/wordfence/) - likely the current number one plugin for WordPress Security. My problem with Wordfence is that _"when you use [Wordfence], statistics about your website visitors are automatically collected"_ (see the full [Terms of Use and Privacy Policy](https://www.wordfence.com/terms-of-use-and-privacy-policy/)). In other words, in order to offer some of its great features, Wordfence is [phoning home](https://en.wikipedia.org/wiki/Phoning_home).
1. [All In One WP Security & Firewall](https://wordpress.org/plugins/all-in-one-wp-security-and-firewall/) - another very popular security plugin for WordPress. I have used AIOWPSF for quite some time; it has a lot of features, but also lot of small bugs (sometimes [not that small](https://sumofpwn.nl/advisory/2016/cross_site_scripting_in_all_in_one_wp_security___firewall_wordpress_plugin.html)). I [used to contribute](https://github.com/Arsenal21/all-in-one-wordpress-security/commits?author=chesio) to the plugin, but the codebase is [rather messy](https://github.com/Arsenal21/all-in-one-wordpress-security/pull/34) and after some time I got tired struggling with it.
2. [All In One WP Security & Firewall](https://wordpress.org/plugins/all-in-one-wp-security-and-firewall/) - another very popular security plugin for WordPress. I have used AIOWPSF for quite some time; it has a lot of features, but also lot of small bugs (sometimes [not that small](https://sumofpwn.nl/advisory/2016/cross_site_scripting_in_all_in_one_wp_security___firewall_wordpress_plugin.html)). I [used to contribute](https://github.com/Arsenal21/all-in-one-wordpress-security/commits?author=chesio) to the plugin, but the codebase is [rather messy](https://github.com/Arsenal21/all-in-one-wordpress-security/pull/34) and after some time I got tired struggling with it.
25 changes: 15 additions & 10 deletions bc-security.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
* Plugin Name: BC Security
* Plugin URI: https://github.com/chesio/bc-security
* Description: Helps keeping WordPress websites secure.
* Version: 0.18.1
* Version: 0.19.0
* Author: Česlav Przywara <[email protected]>
* Author URI: https://www.chesio.com
* Requires PHP: 7.3
* Requires WP: 5.5
* Tested up to: 5.8
* Tested up to: 6.0
* Text Domain: bc-security
* GitHub Plugin URI: https://github.com/chesio/bc-security
* Update URI: https://github.com/chesio/bc-security
Expand Down Expand Up @@ -53,13 +53,18 @@
// Register autoloader for this plugin.
require_once __DIR__ . '/autoload.php';

// Construct plugin instance.
$bc_security = new \BlueChip\Security\Plugin(__FILE__, $GLOBALS['wpdb']);
return call_user_func(function () {
// Construct plugin instance.
$bc_security = new \BlueChip\Security\Plugin(__FILE__, $GLOBALS['wpdb']);

// Register activation hook.
register_activation_hook(__FILE__, [$bc_security, 'activate']);
// Register deactivation hook.
register_deactivation_hook(__FILE__, [$bc_security, 'deactivate']);
// Register activation hook.
register_activation_hook(__FILE__, [$bc_security, 'activate']);
// Register deactivation hook.
register_deactivation_hook(__FILE__, [$bc_security, 'deactivate']);

// Load the plugin.
$bc_security->load();
// Boot up the plugin immediately after all plugins are loaded.
add_action('plugins_loaded', [$bc_security, 'load'], 0, 0);

// Return the instance.
return $bc_security;
});
16 changes: 10 additions & 6 deletions classes/BlueChip/Security/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class Admin
* Initialize admin area of the plugin.
*
* @param string $plugin_filename
*
* @return self
*/
public function init(string $plugin_filename): self
Expand All @@ -43,6 +44,7 @@ public function init(string $plugin_filename): self
* Add a page to plugin dashboard menu.
*
* @param \BlueChip\Security\Core\Admin\AbstractPage $page
*
* @return self
*/
public function addPage(Core\Admin\AbstractPage $page): self
Expand All @@ -55,7 +57,7 @@ public function addPage(Core\Admin\AbstractPage $page): self
/**
* @action https://developer.wordpress.org/reference/hooks/admin_init/
*/
public function initAdminPages()
public function initAdminPages(): void
{
foreach ($this->pages as $page) {
$page->initPage();
Expand All @@ -68,7 +70,7 @@ public function initAdminPages()
*
* @action https://developer.wordpress.org/reference/hooks/admin_menu/
*/
public function makeAdminMenu()
public function makeAdminMenu(): void
{
if (empty($this->pages)) {
// No pages registered = no pages (no menu) to show.
Expand All @@ -80,11 +82,11 @@ public function makeAdminMenu()

// Add (main) menu page
add_menu_page(
'', // obsolete as soon as page has subpages
'', // Page title is obsolete as soon as page has subpages.
_x('BC Security', 'Dashboard menu item name', 'bc-security'),
self::CAPABILITY,
$main_page->getSlug(),
'', // obsolete as soon as page has subpages
'__return_empty_string', // Page content is obsolete as soon as page has subpages. Passing an empty string would prevent the callback being registered at all, but it breaks static analysis - see: https://core.trac.wordpress.org/ticket/52539
self::ICON
);

Expand All @@ -110,8 +112,9 @@ public function makeAdminMenu()
*
* @filter https://developer.wordpress.org/reference/hooks/plugin_action_links_plugin_file/
*
* @param array $links
* @return array
* @param string[] $links
*
* @return string[]
*/
public function filterActionLinks(array $links): array
{
Expand All @@ -130,6 +133,7 @@ public function filterActionLinks(array $links): array
* Format counter indicator for menu title for given $page.
*
* @param \BlueChip\Security\Core\Admin\AbstractPage $page
*
* @return string
*/
private function renderCounter(Core\Admin\AbstractPage $page): string
Expand Down
8 changes: 4 additions & 4 deletions classes/BlueChip/Security/Core/Admin/AbstractPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ abstract class AbstractPage
/**
* Output page contents.
*/
abstract public function printContents();
abstract public function printContents(): void;


/**
Expand Down Expand Up @@ -87,7 +87,7 @@ public static function getPageUrl(): string
*
* @param string $page_hook
*/
public function setPageHook(string $page_hook)
public function setPageHook(string $page_hook): void
{
add_action('load-' . $page_hook, [$this, 'loadPage']);
}
Expand All @@ -96,7 +96,7 @@ public function setPageHook(string $page_hook)
/**
* Run on admin initialization (in `admin_init` hook).
*/
public function initPage()
public function initPage(): void
{
// By default do nothing.
}
Expand All @@ -107,7 +107,7 @@ public function initPage()
*
* @action https://developer.wordpress.org/reference/hooks/load-page_hook/
*/
public function loadPage()
public function loadPage(): void
{
// By default do nothing.
}
Expand Down
4 changes: 2 additions & 2 deletions classes/BlueChip/Security/Core/Admin/CountablePage.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ trait CountablePage
*
* @param \BlueChip\Security\Modules\Countable $counter
*/
protected function setCounter(\BlueChip\Security\Modules\Countable $counter)
protected function setCounter(\BlueChip\Security\Modules\Countable $counter): void
{
$this->counter = $counter;
}
Expand All @@ -27,7 +27,7 @@ protected function setCounter(\BlueChip\Security\Modules\Countable $counter)
/**
* Reset count(er).
*/
protected function resetCount()
protected function resetCount(): void
{
$user = wp_get_current_user();
// Update $user's last view time for this page.
Expand Down
6 changes: 3 additions & 3 deletions classes/BlueChip/Security/Core/Admin/ListingPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ trait ListingPage
private $per_page_option_name;


abstract protected function initListTable();
abstract protected function initListTable(): void;


/**
* @link https://developer.wordpress.org/reference/hooks/set-screen-option/
*
* @param string $option_name
*/
private function setPerPageOption(string $option_name)
private function setPerPageOption(string $option_name): void
{
$this->per_page_option_name = $option_name;

Expand All @@ -36,7 +36,7 @@ private function setPerPageOption(string $option_name)
/**
* @link https://developer.wordpress.org/reference/functions/add_screen_option/
*/
private function addPerPageOption()
private function addPerPageOption(): void
{
add_screen_option('per_page', [
'label' => __('Records', 'bc-security'),
Expand Down
Loading

0 comments on commit 96e2e29

Please sign in to comment.