Make WordPress Core

Opened 10 years ago

Closed 8 years ago

Last modified 4 years ago

#26273 closed enhancement (wontfix)

Deactivated plugins and themes should not execute

Reported by: kirrus's profile kirrus Owned by:
Milestone: Priority: normal
Severity: normal Version:
Component: Administration Keywords:
Focuses: Cc:

Description

Basically, if a plugin is web-accessible, but not active, users are less likely to upgrade it. Additionally, having unused third-party code lying around web-accessible isn't nominal.

It'd be nice if wordpress, as it de-activated a plugin on a user request from the admin panel, and if it was able to, automatically changed the file permissions (chmod in linux) to 000, such that the plugin file wouldn't be accessible directly remotely.

That would reduce the code footprint, and so negate any security vulnerabilities in the inactive plugins.

This is mostly just a would-be-nice, but it could help reduce the likely good of automated attacks coming off - like all the previous Timthumb code, which was distributed widely with remote code execution vuln. (thumb.php)

Change History (24)

#1 @Ipstenu
10 years ago

Keep in mind Multisite, where sites will have a plugin active on one site, but not all. That will complicate the mater.

#2 @jeremyfelt
10 years ago

This would remove the ability for the user to reactivate the plugin, as WordPress is only able to access the files as the web user.

#3 @TobiasBg
10 years ago

@jeremyfelt: Not necessarily, I think. If the web user is the owner of the file, it could chmod from 000 to e.g. 644 again, couldn't it?
However, that shows the possible risk: What if the server config/setup is changed while a plugin is deactivated, and the web user is suddenly not the owner anymore? Also, this idea might create access rights problems via FTP, if the FTP user is different from the web user.

So the risks here probably outweigh the possible benefits. A better approach for those who are concerned about the possibility of such security issues probably is to use a .htaccess file that restricts access to /wp-content/plugins/ (except maybe for plugins on a white list that require external access -- which good plugins don't).

#4 @jdgrimes
10 years ago

  • Cc jdg@… added

#5 @dd32
10 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to wontfix
  • Status changed from new to closed

Basically this isn't possible, and the better option would be for us to have a default .htaccess that deny's requests directly to .php files in wp-content/plugins.

In many server configurations, the user doesn't have direct write access to the WordPress files, and as mentioned above, if the server configuration changes, WordPress might not be able to change the permissions back.
Changing the permissions may also result in FTP Servers deciding that the user doesn't have write-access/delete access to the files (I've seen worse), which is also not a great UX.

I'm going to have to say that this is a wontfix, it's not something we can technically do reliably without harming users, and the better method is simply preventing plugins from being accessed directly in the first place (since none should be..)

#6 follow-up: @kirrus
10 years ago

As a shared webhost's techy, I would far far prefer to have the odd customer contact me because they couldn't reactivate their plugins on their own, than have the situation we found this morning where around 3 separate customers contacted me because their sites were hacked, with what seems to have been a remote sql injection attack through outdated core code. Not totally applicable for this ticket, but reducing remote attack surface area available is always beneficial.

I can pretty much guarantee that for those 3, there will be at least 5 customers who haven't noticed their site is compromised yet, and we'll pick it up when our scans starts detecting malware in their homedirs, or unusual quantities of email outbound from their sites.

Woulds it be possible to modify the .htaccess rules dropped by the permalinks system to deny access to the plugins folder? Also, can you confirm that no plugin file should be accessible remotely? If so, we'll look at changing the settings on our servers to globally enforce that.

#7 in reply to: ↑ 6 @SergeyBiryukov
10 years ago

Replying to kirrus:

Woulds it be possible to modify the .htaccess rules dropped by the permalinks system to deny access to the plugins folder? Also, can you confirm that no plugin file should be accessible remotely?

No. Plugins can make HTTP requests to their own files. Most of the time, they should have used wp_ajax_* actions instead, however some might arguably have a valid reason for that.

Last edited 10 years ago by SergeyBiryukov (previous) (diff)

#8 @planetzuda
10 years ago

  • Resolution wontfix deleted
  • Severity changed from minor to normal
  • Status changed from closed to reopened

May we make a suggestion that should satisfy everyone? If a plugin is disabled, no file should be accessed directly, so it would be safe to block access to the ABSPATH for every file in the plugin while deactivated. While we know plugins should already block access to sensitive files, they don't always.

#9 @Ipstenu
10 years ago

  • Resolution set to wontfix
  • Severity changed from normal to minor
  • Status changed from reopened to closed

That goes back to dd32's point though. If the plugin dev isn't doing it in the file, then it's difficult to block PHP files for all possible server configs (.htaccess works for Apache, but not IIS, nginx,etc). Also, again, Multisite. Sometimes a plugin is active on one site and not others, which would make the file accessible and a vector for ALL sites on the network.

#10 @planetzuda
10 years ago

  • Resolution wontfix deleted
  • Status changed from closed to reopened

There are a multitude of options here. To get around the multi-site issue, we can just not apply it to multi-site. We could check to see what plugins are inactive by using is_plugin_inactive. We can check to see this with code like if(!is_multisite() && is_plugin_inactive('hello.php')) { die('this plugin is deactivated'); }

You would have to get a list of deactivated plugins and then provide that variable to is_plugin_inactive, so we block all plugins and use whatever method is decided on. You would also have to set it, so it doesn't die when trying to reactivate a plugin. That should be looked at as psuedo code, just to give an example of what we're thinking.

Last edited 10 years ago by planetzuda (previous) (diff)

#11 @TobiasBg
10 years ago

Ok, but were would you run that code? Running it in WordPress core won't work, as a direct access to a plugin file will not trigger it, as plugins don't load the WordPress files.
The only real possibilities here would be plugins blocking direct file execution by themselves (which many do with a check like defined( 'ABSPATH' ) or die();, or to block the entire request on the server level. This would require that WordPress maintains a "blacklist" (in .htaccess files and similar) which is just too risky and error-prone for server configuration changes.

#12 @planetzuda
10 years ago

  • Severity changed from minor to normal

Yes, best practice is for the plugin author to automatically do this, but this doesn't always happen. As previously stated There are multiple ways to implement this. It could be implemented through the .htaccess or the code could be added to each plugin file when deactivate_plugins is ran or similar functions. There are lots of other ways to handle this, like adding in /* and ending it with */ at the beginning and end of each block of PHP code.

Evaluating risk is important, however it is a bigger risk not to fix this issue then to possibly run into some configuration problems. Kirrus said something very similar to this affect 7 months ago https://core.trac.wordpress.org/ticket/26273#comment:6


Last edited 10 years ago by planetzuda (previous) (diff)

#13 @TobiasBg
10 years ago

  • Resolution set to maybelater
  • Status changed from reopened to closed

Sorry, but editing plugin PHP files will not be a feasible solution here. That's just too unreliable and risky, and there are too many things that can go wrong, given the many different server configurations that WordPress has to support.

Maintaining an .htaccess file (and similar for other webservers) might work, but there are still too many what-ifs and situations that would not be covered (and maybe can not be covered).

Meanwhile, if this is a concern for certain hosts, they could very well proceed by blocking requests to PHP files in the plugins directory on their servers, maybe with a custom white list of plugins.

Remember that this ticket can always be re-opened if a specific way on how to proceed comes up or someone finds a feasible strategy. Please let's leave this closed until that.

#14 @jsimone
10 years ago

  • Resolution maybelater deleted
  • Status changed from closed to reopened
  • Summary changed from If possible, change file permissions on deactivated plugins so they're not web-accessible. to Deactivated plugins and themes should not execute

This is a big issue, and it applies to themes as well. If anything, the WordPress narrative is half the problem because documentation and the community think that if something isn't active, it's safe!

I find it to be completely unacceptable that and application which touts such a secure platform would allow one dumb or malicious theme file to hijack a website even when it isn't active.

The solution might be inconvenient but I think it really needs to be taken seriously. If it breaks multi-site, then fix multi-site. I know I'm coming in a bit late, but a milestone like 4.0 is really the perfect place to address a potentially breaking-change such as this.

The solution could be as simple as renaming files. Heck, change the file extension or package them into an archive.

#15 @jsimone
10 years ago

Oh and themes that depend on one another can be fixed too. Child-themes are already detected in the UI and can become a first-class (supported) feature. All other inactive themes can go bye-bye.

I also started a forum discussion on this topic that is worth referencing:

https://wordpress.org/support/topic/security-concern-inactive-themes-and-plugins-can-execute-code

Last edited 10 years ago by jsimone (previous) (diff)

#16 @SergeyBiryukov
10 years ago

  • Milestone set to Awaiting Review

It all comes down to points outlined in comment:5 and comment:13.

#17 @jsimone
10 years ago

I don't really think those comments pertain to the solutions I proposed. In fact comment 5 seems a bit out of touch with reality.

In many server configurations, the user doesn't have direct write access to the WordPress files

If the user doesn't have write access to WordPress files then the entire Plugin section is useless. Special file permissions are required for installing, updating, deleting,... what's wrong with needing file permissions for deactivating? Put another way: Do we really want to endorse configurations where WP administrators can't even keep their plugins and core install up to date? Isn't that the exact opposite of what we are trying to encourage?

I agree with comment 13 to an extent.

Sorry, but editing plugin PHP files will not be a feasible solution here. That's just too unreliable and risky, and there are too many things that can go wrong, given the many different server configurations that WordPress has to support.

Editing PHP code is definitely overkill and unreliable. But renaming, archiving, or moving plugin files would all be appropriate, and fairly trivial. Zip files already drive plugin installs. What's wrong with packaging them back up when they are deactivated?

Let me propose an example of what I think is a very viable exploit for WordPress today:

There are at least tens of thousands of WordPress themes out there. There are also a lot of third-party websites distributing themes. I think it is fair to say that the perception of a theme is that it is fairly lightweight and doesn't present the same security concerns as an out of date plugin.

Unsavory characters could obtain some popular or attractive open-source themes and (discretely) inject PHP backdoor code. They could rename the themes and upload them to a slew of community websites. Heck the sheer number of themes in the wild might make it trivial to just find a few with pre-existing issues. Then, botnets could scan websites for the malicious theme names and exploit the backdoors for further nefarious deeds. This could all be done even without a user ever activating the theme in question.

I think the community is moving toward doing whatever it takes to put security front-and-center. Isn't that what introducing automatic core updates is all about? I'm sure making that the default setting was a contention topic at one point. I think the benefits again outweigh the excuses in this case and the problem should be addressed.

#18 @jsimone
10 years ago

Here's a nice anecdote to add. My site was hacked recently (hence my interest in this subject). It appears certain that the MailPoet extension which I use was the cause.

This article claims that this exact vulnerability could be exploited without having the plugin enabled. What a coincidence... That fact may be a large part of why this exploit has reportedly affected so many, and why WordPress will again get a lot of the wrong kind of attention.

http://www.itpro.co.uk/security/22774/50000-sites-hit-by-mailpoet-wordpress-plug-in-security-flaw

#19 @mboynes
9 years ago

I have another proposal for addressing this issue. I (mostly) agree with @jsimone's comment,

the community think that if something isn't active, it's safe!

What if the plugin page were to use design elements and notices to remind users that inactive plugins aren't assumed to be safe? Furthermore, when a plugin is deactivated, core could record the deactivation timestamp and the message could include useful information for the user, "This plugin was last active on yyyy-mm-dd". With multisite, this could happen on the network plugins screen, and it could hypothetically note the last deactivation time across the entire network (we'd want this to be an infrequent cron task which stored the result in a transient, as this would be an expensive poll for a network with thousands of sites or more).

If we add transparency, data, and education, we don't immediately solve the problem, but I think we will mitigate it significantly (and if we add hooks to the check, we make it simple for plugins to genuinely solve the problem by e.g. automatically deleting other plugins which have been inactive for a month).

Probably goes without saying, but all this applies to themes too, with considerations for parent/child themes as applicable.

#20 @chriscct7
8 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to wontfix
  • Status changed from reopened to closed

Per comment:5 and comment:13 closing as wontfix.

Please note, discussion can continue while the ticket is closed. It does not need to be reopened for that to continue.

#21 @SergeyBiryukov
4 years ago

#50590 was marked as a duplicate.

#22 @KestutisIT
4 years ago

.htaccess deny from all auto-blocker if plugin got deactivated + WordPress internal firewall:


So, from discussion in forums, it appears,
that website may also be hacked via deactivated plugin. So after a plugin has been deactivated, I suggest the following:


FOR APACHE SERVERS:
WordPress would automatically create .htaccess file in plugin's folder with "deny from all" content. That would prevent from non-updated deactivated plugin vulnerability, as often people believes, that they are safe if they got deactivated suspicions plugin, of they tested something and left that plugin on the server as deactivated for years.
Also, there should be WordPress internal firewall, that should show BIG RED WARNING in all WP Admin that WordPress was not able to create .htaccess blocker for some plugin, and that user has to create that file with that content manually.

FOR NGIX SERVERS:
There is Apache to NGIX converter. Maybe there has to be IF/ELSE case. In case A - .htaccess file is created, on case B - NGIX directive has been created.

There is Apache's .htaccess to NGIX directives converter:
https://winginx.com/en/htaccess#:~:text=About%20the%20htaccess%20to%20nginx,ported%20from%20Apache%20to%20nginx.
It gives 'deny all' directive for NGIX.

With PHP script you can check if you have access to that 'X' folder or not.
If you still have it, and you see it's NGIX, you put a red warning text saying:

Please immediately contact your server administrator to add this NGIX directive:

/../x-user/.../.../x-plugin/ deny all



This would boost WordPress security level to next class.

Last edited 4 years ago by KestutisIT (previous) (diff)

#23 follow-up: @Ipstenu
4 years ago

Again, please keep multisite in mind. If I deactivate a plugin on one site in the network, I would like it to keep working for the others :) This is also true if I global deactivate a plugin. I may still want to activate it on individual sites after, and assuming that I don't can open up a rat's nest.

#24 in reply to: ↑ 23 @KestutisIT
4 years ago

Replying to Ipstenu:

Again, please keep multisite in mind. If I deactivate a plugin on one site in the network, I would like it to keep working for the others :) This is also true if I global deactivate a plugin. I may still want to activate it on individual sites after, and assuming that I don't can open up a rat's nest.

Then one more check probably needed that would do the check:
"if plugin is nor network activated, nor in any of sub-sites individually", then put this .htaccess file /ngix requirement.
As we in SolidMVC micro-framework upgradings already went over those checkings, it is possible with some extra lines of code check that. And remove .htaccess in case plugin is .network-activated, or .locally-activated-in-at-least-one-site.

Of course, there could be another way to solve it - offer PHP.net team to add to PHP 8.0 a feature to mark folder web-inaccessible (similar to chmod rights). Or even we can be changing chmod rights with remove of 'execute' permission from user-level. Meaning then the files would not allow execution. Maybe chmod permission changing can be even easier solution, but I'm not sure if this is supported by chmod.

As same as PHP has now file directives for STRICT, it could also have FOLDER directive for web-accessible or not. But until PHP 8, I'd suggest to go with .htaccess / ngix directive recommendation, or maybe with CHMOD exec ON/OFF setter.

Last edited 4 years ago by KestutisIT (previous) (diff)
Note: See TracTickets for help on using tickets.