In continuing to work on improving our Plugin Security Checker, which does limited automated security checks of WordPress plugins (and is now accessible through a WordPress plugin of its own), we have been interested to see where it can already provide value over what is already being done to improve the security of plugins. We recently got what looks to be an example of it catching something that was missed by the team managing the Plugin Directory.
Last Tuesday we were contacted by one of our customers, J.D. Grimes, to let us know that he had noticed that an attempt to fix a vulnerability in the plugin Media from FTP looked like it had failed to fully fix the vulnerability, but he didn’t have time to verify that or contact the developer about that. We took a look, confirmed that the fix was incomplete, and then worked with the developer to implement a better fix. A new version with that second fix was released later the same day.
At some point on Thursday the plugin was closed on the Plugin Directory. No explanation was given why that was, but based on the subsequent changes made and past experience, we would guess that the plugin was belatedly closed due the then fixed vulnerability and then the Plugin Directory required additional changes be made based on a privacy and security review done after it was removed. According to their documentation that should involve the following:
- Don’t phone home without informed user consent
- Collection of user data must be “opt-in” only and have the relevant option set to disabled by default
- Validate and sanitize untrusted data before processing (See: Data Validation)
- Escape all data before output (See: Data Validation)
- Do not use URL shorteners
- Use prepare() and $wpdb for SQL calls
Sometime on Thursday prior to the plugin having been closed someone ran the plugin through our Plugin Security Checker and it detected a possible issue. We have been doing spot checks on what is being flagged by that to improve the quality of the results (last week we fixed one false positive and another issue that could have lead to false positives through that), so we went to check on that. Looking at the details of the issue identified, which are available through the tool’s new Developer Mode, it certainly looked like there could be a reflected cross-site scripting (XSS) vulnerability as user input was being output without being escaped:
A quick check confirmed that this was an exploitable vulnerability (though far from a serious issue for the average website), as can be seen with the proof of concept below.
That should have been something caught by a check meant to insure that “Escape all data before output (See: Data Validation)”. Many of the changes made to the plugin after it was removed from the directory dealt with sanitizing user input, so this seems like something that should have also been caught, but the plugin returned to the directory without it being fixed.
Yesterday we contacted the developer and they released a new version, 9.90, which fixes the vulnerability by replacing the variable used (since previously a different value than intended one could be shown) and the value is escaped using esc_attr():
<input name="page" type="hidden" value="<?php echo esc_attr($_GET['page']); ?>" />
This seems to show using our tool could improve the security reviews that are supposed to be being done by the Plugin Directory to catch this type of issue as well as more serious issues. As we have said in the past, we would be happy to provide free access to the Plugin Directory team to the portions of the tool that normally are restricted to those using our service.
This also seems like further confirmation that that when the tool detects a possible reflected cross-site scripting (XSS) vulnerability that it is a good indication that a plugin could use a more thorough review, considering the other recently fixed issues in this plugin.
Proof of Concept
The following proof of concept will cause an alert box with the message “XSS” to be shown. Major web browsers other than Firefox provide XSS filtering, so this proof of concept will not work in those web browsers.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/wp-admin/admin.php?page=mediafromftp-search-register" method="POST"> <input type="hidden" name="page" value='"><script>alert(document.cookie);</script>' /> <input type="submit" value="Submit" /> </form> </body>
- January 16, 2018 – Developer notified.
- January 16, 2018 – Version 9.90 released, which fixes the issue.