Skip to content

Commit

Permalink
Merge pull request #24 from igorhrcek/issue-23
Browse files Browse the repository at this point in the history
Issue 23
  • Loading branch information
igorhrcek authored Mar 20, 2022
2 parents 69df9a3 + 1dcfad1 commit 13c5364
Show file tree
Hide file tree
Showing 22 changed files with 273 additions and 126 deletions.
46 changes: 42 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,20 @@ Removes all security rules.
wp secure flush
```

### Block access to sensitive files and directories
### Block the access to sensitive files and directories
```bash
wp secure block-access <what-to-block>
```

Blocks direct access to sensitive files and directories:
By default, this command blocks the direct access to sensitive files and directories:
`readme.txt`, `readme.html`, `xmlrpc.php`, `wp-config.php`, `wp-admin/install.php`, `wp-admin/upgrade.php`, `.git`, `svn`, `cache` and `vendors`

Possible options are:
- sensitive-files
- sensitive-directories
- xmlrpc
- htaccess
- custom
- all (does all the above)

Examples:
Expand All @@ -45,6 +46,18 @@ wp secure block-access htaccess
wp secure block-access all
```

However, you can also block custom files and/or folders of your choice. To do that you should use `custom` argument
and pass one of two additional options `--files` and/or `--directories`.

If you want to block custom files, make sure that you pass only file names, not a full file paths.

Examples:

````bash
wp secure block-access custom --files=dump.sql,phpinfo.php,adminer.php
wp secure block-access custom --directories=wp-content/mu-plugins
````

### Block Author Scanning

```bash
Expand Down Expand Up @@ -91,7 +104,7 @@ wp secure disable-directory-browsing

Disables directory browsing.

By default when your web server does not find an index file (i.e. a file like index.php or index.html), it
By default, when your web server does not find an index file (i.e. a file like index.php or index.html), it
automatically displays an index page showing the contents of the directory.
This could make your site vulnerable to hack attacks by revealing important information needed to exploit a vulnerability in a WordPress plugin, theme, or your server in general.

Expand All @@ -110,6 +123,31 @@ This makes it easier for attackers to change files on the server using a web bro
wp secure disable-file-editor
```

### Fix file and directory permissions

```bash
wp secure fix-permissions
```

Use this command to verify that the permissions of all files and directories are set according the WordPress recommendations.
This command will set **0666** to all files and **0755** to all folders inside WordPress installation.

**IMPORTANT: Don't use this command if you don't know what you are doing here!**

### Check the integrity of WordPress files

Downloads MD5 checksums for the current version from WordPress.org, and compares those checksums against the currently
installed files.

It also returns a list of files that shouldn't be part of default WordPress installation, which can be very useful when you are
looking for a possible injected files.

Examples:

```bash
wp secure integrity-scan
```

## Global options

### Remove single security rule
Expand Down Expand Up @@ -143,7 +181,7 @@ wp secure block-access htaccess --file-path=/home/user/mysite.com/.htaccess
```

## Important Note for nginx users
nginx rules are stored in the `nginx.conf` file. However, for rules to actually work, you need to manually include this file in your vhost configuration and then restart nginx server:
The nginx rules are stored in the `nginx.conf` file. However, for rules to actually work, you need to manually include this file in your vhost configuration and then restart nginx server:
```
systemctl restart nginx
```
Expand Down
167 changes: 99 additions & 68 deletions src/SecureCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use WP_CLI;
use WP_CLI_Command;
use WP_CLI_Secure\SubCommands\BlockAccessToCustomSensitiveFiles;
use WP_CLI_Secure\SubCommands\BlockAccessToHtaccess;
use WP_CLI_Secure\SubCommands\BlockAccessToSensitiveDirectories;
use WP_CLI_Secure\SubCommands\BlockAccessToSensitiveFiles;
Expand Down Expand Up @@ -33,7 +34,7 @@
* Success: Directory Browsing is disabled.
*
* # Remove security rule
* $ wp secure disable-directory-browsing --disable
* $ wp secure disable-directory-browsing --remove
* Success: Directory Browsing is enabled.
*
* # Remove all security rules
Expand Down Expand Up @@ -76,27 +77,25 @@ class SecureCommand extends WP_CLI_Command {
*
* ## EXAMPLES
*
* $ wp secure disable_directory_browsing
* $ wp secure disable-directory-browsing
* Success: Directory Browsing security rule is now active.
*
* @subcommand disable-directory-browsing
*
* @when before_wp_load
*/
public function disable_directory_browsing($args, $assoc_args) : void {
(new DisableDirectoryBrowsing($assoc_args))->output();
}

/**
* Disables execution of PHP files in Plugins.
* Disables execution of PHP files in Plugins, Uploads, Themes and wp-includes.
*
* PHP files in `wp-content/plugins` directory shouldn't be directly accessible. This is important in case of malware injection as it prevents attacker
* from directly accessing infected PHP files
* PHP files in certain directories shouldn't be directly accessible. This is important in case of malware injection as it prevents attacker from directly accessing infected PHP files
*
* ## OPTIONS
*
* <block-part>
* : Required. accepts: plugins, uploads, includes, themes or all.
* <what-to-block>
* : Required. Accepts: plugins, uploads, includes, themes or all.
*
* [--remove]
* : Removes the rule from .htaccess or nginx.conf.
Expand All @@ -113,58 +112,64 @@ public function disable_directory_browsing($args, $assoc_args) : void {
*
* ## EXAMPLES
*
* # Apply the block rules for plugins
* # Apply the block rules for plugins directory
* $ wp secure block-php plugins
* Success: Block Execution In Plugins Directory rule has been deployed.
*
* # Apply the block rules for all parts.
* # Apply the block rules for all directories
* $ wp secure block-php all
* Success: Block Execution In Plugins Directory rule has been deployed.
*
* @when before_wp_load
*
* @subcommand block-php-execution
* @when before_wp_load
*/
public function block_php($args, $assoc_args) : void {
$blockPart = $args[0];

$block_part = $args[0];
$allowedArguments = [
'plugins', 'uploads', 'wp-includes', 'themes', 'all'
];

// Failure first.
if ( ! in_array( $block_part,
array( 'plugins', 'uploads', 'wp-includes', 'themes', 'all' ),
true )
) {
WP_CLI::error( sprintf( 'Invalid block part "%s" was provided. Allowed values are "plugins", "uploads", "includes", "themes" or "all"',
$block_part ) );
if(!in_array($blockPart, $allowedArguments, true)) {
WP_CLI::error(
sprintf('Invalid block part "%s" was provided. Allowed values are "plugins", "uploads", "includes", "themes" or "all"',
$blockPart)
);
}

if ( 'all' === $block_part || 'plugins' === $block_part ) {
WP_CLI::debug( 'Securing the plugins folder.', 'secure');
( new BlockPhpExecutionInPlugins( $assoc_args ) )->output();
}
if ( 'all' === $block_part || 'uploads' === $block_part ) {
WP_CLI::debug( 'Securing the uploads folder.', 'secure');
( new BlockPhpExecutionInUploads( $assoc_args ) )->output();
}
if ( 'all' === $block_part || 'wp-includes' === $block_part ) {
WP_CLI::debug( 'Securing the includes folder.', 'secure');
( new BlockPhpExecutionInWpIncludes( $assoc_args ) )->output();
}
if ( 'all' === $block_part || 'themes' === $block_part ) {
WP_CLI::debug( 'Securing the themes folder.', 'secure');
( new BlockPhpExecutionInThemes( $assoc_args ) )->output();
}
if(in_array($blockPart, ['all', 'plugins'])) {
WP_CLI::debug('Securing the plugins folder.', 'secure');
(new BlockPhpExecutionInPlugins($assoc_args))->output();
}

if(in_array($blockPart, ['all', 'uploads'])) {
WP_CLI::debug('Securing the uploads folder.', 'secure');
(new BlockPhpExecutionInUploads($assoc_args))->output();
}

if(in_array($blockPart, ['all', 'wp-includes'])) {
WP_CLI::debug('Securing the wp-includes folder.', 'secure');
(new BlockPhpExecutionInWpIncludes($assoc_args))->output();
}

if(in_array($blockPart, ['all', 'themes'])) {
WP_CLI::debug('Securing the themes folder.', 'secure');
(new BlockPhpExecutionInThemes($assoc_args))->output();
}
}

/**
* Blocks direct access to various sensitive files and directories
*
* Blocks direct access to readme.html, readme.txt, wp-config.php and wp-admin/install.php files.
* Blocks direct access to sensitive files such as readme.html, readme.txt, wp-config.php and wp-admin/install.php files.
* It also blocks the direct access to a certain number of directories such as .git, svn, cache and vendors.
*
* You can use this command to block access to custom files and folders as well.
*
* ## OPTIONS
*
* <block-part>
* : This option is required. Accepts one of the following values: sensitive-files, sensitive-directories, htaccess, xmlrpc or all.
* <what-to-block>
* : This option is required. Accepts one of the following values: sensitive-files, sensitive-directories, htaccess, xmlrpc, custom or all.
*
* [--remove]
* : Removes the rule from .htaccess or nginx.conf.
Expand Down Expand Up @@ -192,34 +197,53 @@ public function block_php($args, $assoc_args) : void {
* $ wp secure block-access all
* Success: Block Access to Sensitive Files rule has been deployed.
*
* @subcommand block-access
* # Block custom files and directories
* $ wp secure block-access custom --files=dump.sql --directories=some/directory
* Success: Block Access to Sensitive Files rule has been deployed.
*
* @subcommand block-access
* @when before_wp_load
*/
public function block_access($args, $assoc_args): void {
$block_part = $args[0];
$blockPart = $args[0];

$allowedSubArguments = [
'sensitive-files', 'sensitive-directories', 'htaccess', 'xmlrpc', 'all', 'custom'
];

// Failure first.
if ( ! in_array( $block_part, array( 'sensitive-files', 'sensitive-directories', 'htaccess', 'xmlrpc', 'all' ), true ) ) {
WP_CLI::error( sprintf( 'Invalid block part "%s" was provided. Allowed values are "files", "directories", "htaccess", "xmlrpc" or "all"', $block_part ) );
if(!in_array( $blockPart, $allowedSubArguments, true)) {
WP_CLI::error(sprintf('Invalid block part "%s" was provided. Allowed values are ' . implode(', ', $allowedSubArguments), $blockPart));
}

if ( 'all' === $block_part || 'sensitive-files' === $block_part ) {
WP_CLI::debug( 'Blocking access to the sensitive files.', 'secure');
if(in_array($blockPart, ['all', 'sensitive-files'])) {
WP_CLI::debug('Blocking access to the sensitive files.', 'secure');
(new BlockAccessToSensitiveFiles($assoc_args))->output();
}
if ( 'all' === $block_part || 'sensitive-directories' === $block_part ) {
WP_CLI::debug( 'Blocking access to the directories.', 'secure');
( new BlockAccessToSensitiveDirectories( $assoc_args ) )->output();
}
if ( 'all' === $block_part || 'htaccess' === $block_part ) {
WP_CLI::debug( 'Blocking access to the htaccess.', 'secure');
(new BlockAccessToHtaccess($assoc_args))->output();
}
if ( 'all' === $block_part || 'xmlrpc' === $block_part ) {
WP_CLI::debug( 'Blocking access to the xmlrpc.', 'secure');
(new BlockAccessToXmlRpc($assoc_args))->output();
}
}

if(in_array($blockPart, ['all', 'sensitive-directories'])) {
WP_CLI::debug('Blocking access to the directories.', 'secure');
(new BlockAccessToSensitiveDirectories($assoc_args))->output();
}

if(in_array($blockPart, ['all', 'htaccess'])) {
WP_CLI::debug('Blocking access to the htaccess.', 'secure');
(new BlockAccessToHtaccess($assoc_args))->output();
}

if(in_array($blockPart, ['all', 'xmlrpc'])) {
WP_CLI::debug('Blocking access to the xmlrpc.', 'secure');
(new BlockAccessToXmlRpc($assoc_args))->output();
}

//Custom files and directories blocking
if($blockPart === 'custom' && isset($assoc_args['files'])) {
(new BlockAccessToCustomSensitiveFiles($assoc_args))->output();
}

if($blockPart === 'custom' && isset($assoc_args['directories'])) {
(new BlockAccessToSensitiveDirectories($assoc_args))->output();
}
}

/**
Expand Down Expand Up @@ -248,11 +272,10 @@ public function block_access($args, $assoc_args): void {
*
* ## EXAMPLES
*
* $ wp secure block_author_scanning
* $ wp secure block-author-scanning
* Success: Block Author Scanning rule has been deployed.
*
* @subcommand block-author-scanning
*
* @when before_wp_load
*/
public function block_author_scanning($args, $assoc_args) : void {
Expand All @@ -262,8 +285,8 @@ public function block_author_scanning($args, $assoc_args) : void {
/**
* Removes all WP CLI Secure rules
*
* Use this command to remove all deployed security rules. If you are using nginx you need to restart it. If you copied rules manually, this command
* will not remove them!
* Use this command to remove all deployed security rules. If you are using nginx you need to restart it.
* If you copied rules manually, this command will not remove them!
*
* ## OPTIONS
*
Expand Down Expand Up @@ -305,18 +328,22 @@ public function flush($args, $assoc_args) : void {
* @subcommand integrity-scan
* @when before_wp_load
*/
public function integrityscan($args, $assoc_args) : void {
public function integrity_scan($args, $assoc_args) : void {
WP_CLI::runcommand('core verify-checksums');
}

/**
* Disable the file editor in WordPress
*
* @subcommand disable-file-editor
* The problem with the WordPress file editor is that it allows users to run PHP code on your site.
* Anytime a user is able to run their own code, this presents a security risk.
* If an insecure admin account is hacked, the WordPress file editor is the gateway through which a full-fledged attack can be
* carried out.
*
* @param $args
* @param $assoc_args
*
* @subcommand disable-file-editor
* @when before_wp_load
*
* @return void
Expand All @@ -326,15 +353,17 @@ public function disable_file_editor($args, $assoc_args) : void {
}

/**
* Fix all directory and file permissions of the wordpress installation
* Fix all directory and file permissions of the WordPress installation
*
* Use this command to verify that the permissions of all files and directories are set according the WordPress recommendations.
* This command will set 0666 to all files and 0755 to all folders inside WordPress installation.
*
* Use this command to verify that the permissions of all files and directories are set according the wordpress recommendations.
* IMPORTANT: Don't use this command if you don't know what you are doing here!
* IMPORTANT: Don't use this command if you don't know what you are doing here!
*
* ## EXAMPLES
*
* $ wp secure fix-permissions
* Success: All permission are reset to wordpress default.
* Success: All permission are set to the WordPress recommended values.
*
* @subcommand fix-permissions
* @when before_wp_load
Expand All @@ -348,6 +377,8 @@ public function fix_permissions($args, $assoc_args) : void {
/**
* Deploys all security rules at once
*
* This command will deploy all security rules at once.
*
* ## EXAMPLES
*
* $ wp secure all
Expand Down
Loading

0 comments on commit 13c5364

Please sign in to comment.