Last week a vulnerability in the WordPress plugin Fancybox for WordPress was exploited causing many websites to serve malware. A week later we thought it would be a good time to look at what went wrong and what lessons can be taken from the incident to hopefully improve WordPress plugin security going forward.
WordPress Plugin Security is in Bad Shape
When we started to look in to this, what we were most interested to see was what was the underlying vulnerability that allowed the websites to be hacked. Was it some obscure corner case that allowed a hacker access they shouldn’t have or was it some very fundamental failure? Since the developer stated they fixed the vulnerability in version 3.0.3 looking at the changes in that version was the starting place for understanding that. What the changes made show is that anyone could change the plugin’s settings. By anyone we truly me anyone, you didn’t have to be logged in to WordPress to change the settings. This wasn’t the intention of the developer, as can be see by the fact that only logged in users who are Administrators can access the plugin’s settings page.
The problematic code is the code for saving the settings, which did not check to make sure that the settings change came from the setting’s page. In 3.0.2 the code simply checked if a request for a setting updates was sent and then went on to save the settings:
if ( isset($_REQUEST[‘action’]) && ‘update’ == $_REQUEST[‘action’] ) {
The changed code in 3.0.3 checks to see where the request came from as well:
if ( isset($_REQUEST[‘action’]) && ‘reset’ == $_REQUEST[‘action’] && check_admin_referer( ‘mfbfw-options-options’ ) ) {
In many cases being able to change a plugin’s settings would not allow it to be used to serve malware. What allowed it in this cases is that the plugin has settings that allow additional code to be added to pages in which FancyBox for WordPress is present:
All the hacker had to do was to update the settings to turn on that feature and have it use their malicious code.
The fact that a plugin that now has over 600,000 downloads (each time an installed plugin is updated in WordPress that gets included in the download count, so the amount of websites using it is much lower) allowed anyone to change it’s settings and a hacker was the first person to discover this isn’t a good sign for the security of WordPress plugins. We think that Automattic has at least some responsibility for improving this situation.
The response after the fact was much better. The vulnerability was quickly fixed and WordPress automatically pushed the updated version for those running at least WordPress 3.7 (which introduced automatic updates)
Understanding the Scope of Vulnerability
When dealing with a hacked website an important element in the cleanup process is understanding the scope of the exploitation, so that appropriate cleanup action is taken. While it doesn’t hurt to do more than what is needed, it can take more time and increase expenses, which can be a major hardship depending on the website.
In this case the direct impact of the vulnerability is somewhat limited. The hacker is able to add code to the setting and that is loaded on pages on the website but because the setting is stored in the database safely using the update_option function they can not otherwise gain access the database through the vulnerability. It is possible for malicious JavaScript to provide the hacker additional access to the website if an admin was to have visited a page that has the code on it while logged in.
Once a website upgraded to at least version 3.0.4, any malicious code currently stored in the setting is disabled and the vulnerability is patched, so the website should be secure at that point, but you may want take the precautionary measures of changing the passwords associated with the website and checking over the website for malicious code or reverting the website to a backup made before the website was originally hacked.
The Settings API
When looking at how to improve code security, hoping that people will start writing secure code on their own isn’t a good bet. Some combination of making it easier to do things securely and making it harder to write insecure code seems to be an important element to improving the situation.
So could be something be done to deal with this type of situation? There already is a way to handle saving settings securely, the Settings API, which was introduced in WordPress 2.7. This API handles managing settings and only allows settings to be saved by users with manage_options capability, which is normally only given to Administrators (and Super Admins when using MultiSite). The problem with it is that it doesn’t appear to be used in many plugins (that includes our plugin with a settings page, which we are looking to rectify). It would be worth looking in to how to make it so that it is more widely used going forward.
Security Journalism is in Bad Shape
You don’t have to follow IT security closely to know that it isn’t in good shape these days, with major company after company revealing that sensitive customer data has been breached. Good IT security journalism could be an important piece of shining a light on bad practices (which are abundant) and ultimately getting security where it should be. Unfortunately, what we have found is that security journalism is in as bad or worse shape than the security they cover. Take for instance The Register’s article on the situation with this plugin. It misses many important details, like the fact the plugin was being automatically updated for many and that the update would take care of much of the issue. It then follows that up with some truly bad reporting:
The vulnerability followed what was described as the “most serious” hole in five years, disclosed last November, that affected what was then estimated to be 86 per cent of WordPress websites. That cross-site scripting hole was found in the hugely-popular WP-Statistics plugin.
First off we have yet to see any impact from the vulnerability that is mentioned as being the “most serious” hole in five years, its limited impact would be something to mention several months after it was fixed in outdated installs (the current version at the time was not vunerable, which would have been worth mentioning as well). The bigger mistake is that the author of the article is conflating a vulnerability in WordPress itself with an unrelated vulnerability in the the WP-Statistics plugin, despite having also written the article they are citing about the previous vulnerability.