Stop leaking information

In the past I used to write my own simple CMS (Content Management System) for my own website and for friends. This ensured every website did exactly what everyone needed, but had to be maintained by me. WordPress takes all that hassle away and has an incredulous amount of themes and plugins available right out of the box. It also allows for an enormous level of tweaking. Each and every call is pretty much “hookable”, allowing anyone to write a plugin to do anything they wish when a function is called. This all allows for great flexibility, but for me – trying to host WordPress from my seven year old NAS – pages can take a long time to load. Up to ten second per page. Adding plugins from the store that promise caching, were only speeding up the site by a second or so as most of the PHP-code in most of the files was still being executed.
On the other hand, setup for a WordPress-site is so easy;
With the enormous user-base that WordPress has, as new exploits are found and released into the wild, hackers roam free and kidnap WordPress websites by the thousands. These websites are frequently used for phishing scams and hosting malware. In one event, a hacker group who infiltrated high ranking government officials for a country I can’t remember, used a couple compromised WordPress site as their C2 (Command and Control) servers.
With the (currently) most recent patch 4.7.2, a vulnerability was discovered in the REST-API, allowing anyone to post any message to any WordPress-website. Even though most actual WordPress users have no idea what a REST API is and why they are running it on their site, apparently it has been enabled by default starting in WordPress 4.7. A quick look in the admin panel showed no way of disabling this API either.

So… many… features…

There’s a tool available online called WPScan, which does exactly what it says. It lets anyone scan any WordPress installation and it will tell you so many things about the website. Apparently WordPress inserts version numbers everywhere, has dozens of features that are “always-on”, but (for me) lead to no extra functionality.
Extra features are not always a good thing. I mean, sure, for the administrator and the user, they probably are. But as in most cases, more features mean more code to maintain. As the codebase grows, you would expect the same for any bugs which can be exploited.
Googling for how to disable most of the WordPress-features, leads  to writing PHP-code into your /wp-content/functions.php  directly. This most likely works fine, but any WordPress update will update the file, deleting your lines in the process.
As such, I have taken matters into my own hands. Looking through the available plugins did not leave me with a very good feeling. Most plugins promising security either require payment or consist of dozens of files, leaving me no quick way to audit the code. By writing a “plugin” PHP-script, which needs to be enabled in the WordPress admin area, the script does not touch any core WordPress files and should never be manipulated by any update.
Instead of providing the entire file, with no context, I will do a quick rundown of most features I have disabled and why I have done this.

Firstly, complying with WordPress plugin dynamics

So, before we put any code down, WordPress expects to extract some basic information from the file, it looks a little like this:

There’s some information in there, which WordPress expects: an  author, a name and and description it can display for the plugin etc.
In  addition, there’s a quick check for the constant ABSPATH  as this is a constant set by WordPress and if it’s not there, the plugin is not requested  by WordPress and we better not call any functions.

WordPress “features”

There are a number of “features” in WordPress that I do not think of as features, such as:

  1. Generator tags on every page, specifying that WordPress was used to generate this page.
  2. An RSS-feed, which leaks data such as a version number.
  3. A REST-API for which I have no use and do not want anyone else to use.
  4. XMLRPC, which allows for “pingbacks” (saying: I linked to your page from my page!), but in the past have been used for DDoS attacks. Personally,  I have no interest in who would link to me.
  5. Adding query parameters to stylesheets, specifying which WordPress version I’m using.
  6. Providing a nice readme.html file which sits in almost anyones WordPress installation, telling anyone who’s interested what version I am running.

For most of these, they “leak” information that I do not want everyone to know. This includes, for example, my WordPress-version. Even though I update my WordPress whenever I can, this does not mean I am not a human and cannot forget.
For most of the above, I am simply checking the URL and killing the script when it detects a URL being requested that I do not want available. For others, I have simply reduced the file permissions to  “000”  (no read access, no write access, no execute access), meaning my webserver is not able to read the file and thus shows a “Forbidden” screen. This also means WordPress will not be able to update the file or change any permissions on it. Effectively taking it out.

Disabling WordPress “features”

For the readme.html, all I did was reduce the file permissions to 000, allowing nobody to  access to the file.

Hooking into function calls

Most google results for “disabling xxx wordpress” will lead to adding code to pages which consist of add_filter('filter_name', '__return_false');  meaning they will no longer function.
I have combined a few of those here, mostly found through Google:

In addition, as the plugins PHP-code is called on each and every page, before outputting any data to the web browser, I have resorted to simply killing the script on specific requests:

If the URL requested contains /feed , xmlrpc.php  or /wp-json , it simply exits the script and shows no output to the user. This is the most effective way I have found of disabling these “features”.