20 Apr

Security Tip for Developers: You Don’t Need to Restrict Direct Access to .php Files Twice

One of the items we check for during our security reviews of plugins selected by our customers is to see if the plugin’s .php files can be accessed directly when they are not intended to. While being able to access them directly when that isn’t necessary usually doesn’t have any security impact, it is easy to prevent that from happening and it could in some cases prevent serious issues, like a remote code execution (RCE) vulnerability we found being exploited in a security plugin last year.

Something we ran across recently in our monitoring of security changes made to plugins, which allows us to include data on vulnerabilities that you won’t find in other sources of WordPress plugin vulnerability data, indicates that developers implementing such protection don’t always understand what it is that they are implementing.

The changelog entry for the new version of a plugin was “Security plugin fix.”, but in looking at the changes made we found the only change was that the following code was added:

if ( ! defined( 'ABSPATH' ) ) { 
    exit; 
}

That is code that will prevent direct access to the file, as we will explain in a second.

That wasn’t a security fix since the code was added directly below this piece of code:

if ( ! defined( 'WPINC' ) )  die;

While that looks a bit different than the first one, it does exactly the same thing.

Then yesterday in the same plugin another change was made that added the following lines to the beginning of the code in a number of files:

if ( ! defined( 'WPINC' ) )  die; 
if ( ! defined( 'ABSPATH' ) ){ exit;  }

Seeing as both lines do the same thing, we were confused as to what might be going on. We wondered if we were missing something or if we could find an explanation as to what might be going on.

In our search for answers we couldn’t find anyone suggesting doing both of those, but we did run into a StackExchange question from someone wondering which to use. Seeing as there still seems to confusion on this let’s take a closer look at what they both do.

First let’s deal with the easy part of this, “die” and “exit” are the same. PHP just allows you terminate a script with either one.

The first part checks if a constant is defined, which for either “WPINC” or “ABSPATH” will not be true if you make a request directly to a .php file from a plugin. So which one is checked doesn’t make any difference for what is being done. When they are not defined “die” or “exit” executes and no more code in the file will run.

To full explain things though, “WPINC” or “ABSPATH” are constants that are defined when WordPress is loading. Normally, when requesting a front-end page  “ABSPATH” will be defined by the file /wp-load.php and “WPINC” will defined later when the file /wp-settings.php is loaded. Since neither one of those files will have been loaded when first accessing a plugin’s file directly, it doesn’t matter which one you check for, so you just need to add one of those line before the rest of the code in the file to prevent direct access.

Leave a Reply

Your email address will not be published. Required fields are marked *