01 Feb

What Happened With WordPress Plugin Vulnerabilities in January 2018

If you want the best information and therefore best protection against vulnerabilities in WordPress plugins we provide you that through our service.

Here is what we did to keep those are already using our service secure from WordPress plugin vulnerabilities during January (and what you have been missing out on if you haven’t signed up yet):

Plugin Security Reviews

Paid customers of the service can suggest and vote on plugins to have a security review done by us. This month we released details for reviews of:

Plugin Vulnerabilities We Discovered and Publicly Disclosed This Month

We don’t just collect data on vulnerabilities in plugins that others have discovered, we also discover vulnerabilities through proactive monitoring of changes made to plugins, monitoring hackers’ activity, reviewing other vulnerabilities, and by doing additional checking on the security of plugins.

The most concerning vulnerabilities were a couple of vulnerabilities of types highly likely to be exploited in a plugin that was removed from the Plugin Directory 5 years ago but is still installed on 500+ websites according to wordpress.org.

Plugin Vulnerabilities We Helped Get Fixed This Month

Letting you know that you are using a vulnerable version of plugin is useful, but it is much more useful if you can fully protect yourself by simple updating to a new version. So we work with plugin developers to make sure that vulnerabilities get fixed.

Plugin Vulnerabilities Added This Month That Are In The Current Version of the Plugins

Keeping your plugins up to date isn’t enough to keep you secure as these vulnerabilities in the current versions of plugins show:

Additional Vulnerabilities Added This Month

As usual, there were plenty of other vulnerabilities that we added to our data during the month. The most serious vulnerability here being an arbitrary file upload vulnerability in LearnDash LMS that was discovered after it was already being exploited.

17 Jan

It Looks Like Our Plugin Security Checker Caught a Vulnerability That Was Missed by a WordPress Plugin Directory Review

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():

917
<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>

Timeline

  • January 16, 2018 – Developer notified.
  • January 16, 2018 – Version 9.90 released, which fixes the issue.
13 Sep

Authenticated PHP Object Injection Vulnerability in Media from FTP

We recently started proactively monitoring for evidence of some high risk vulnerabilities when changes are made to WordPress plugins and if we had more customers we could expand the proactive monitoring to more types of vulnerabilities. One of the types of vulnerabilities we are looking for are PHP object injection vulnerabilities since those are likely to be exploited if hackers become aware of them. Through that we came across an authenticated PHP object injection vulnerability in the plugin Media from FTP.

The plugin makes the function mediafromftp_medialibraryimport_update_callback() accessible through WordPress’ AJAX functionality to those logged in to WordPress (in the file /mediafromftp.php):

79
add_action( 'wp_ajax_'.$action2, array($mediafromftpajax, 'mediafromftp_medialibraryimport_update_callback') );

As of version 9.79, that function passed the POST input “db_wp_attachment_metadata” through the maybe_unserialize() function, which permits PHP object injection, if the user making the request has the “upload_files” capability and has access to the nonce “mediafromftp-import-ajax-action” (in the file /req/MediaFromFtpAjax.php):

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
function mediafromftp_medialibraryimport_update_callback(){
 
	$action2 = 'mediafromftp-import-ajax-action';
	if ( isset( $_REQUEST['nonce'] ) && wp_verify_nonce( $_REQUEST['nonce'], $action2 ) ) {
		if ( current_user_can( 'upload_files' ) ) {
			$file = $_POST["file"];
			$filepath = str_replace(MEDIAFROMFTP_PLUGIN_UPLOAD_DIR.'/' , '', $file);
			if ( is_file($file) ) {
				if ( !empty($_POST["db_array"]) ) {
					$db_array = $_POST["db_array"];
					global $wpdb;
					$table_name = $wpdb->prefix.'posts';
					$wpdb->insert( $table_name, $db_array );
					update_attached_file( $db_array['ID'], $filepath ) ;
					if ( !empty($_POST["db_wp_attachment_metadata"]) ) {
						$metadata = maybe_unserialize(stripslashes($_POST["db_wp_attachment_metadata"]));

Normally Author-level and above users have the “upload_files”  capability. The nonce is accessible on the plugin’s admin pages, which are also accessible to users with the “upload_files” capability (in the file /req/MediaFromFtpAdmin.php):

76
77
78
79
80
81
82
83
add_menu_page(
		'Media from FTP',
		'Media from FTP',
		'upload_files',
		'mediafromftp',
		array($this, 'manage_page'),
		'dashicons-upload'
);

The day after we notified the developer of the vulnerability they released version 9.80, which fixes the vulnerability by using replacing the usage of maybe_unserialize() with json_decode().

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, the following proof of concept will cause the message “PHP object injection has occurred.” to be shown, when logged in as a user that has the  “upload_files”  capability.

Make sure to replace “[path to WordPress]” with the location of WordPress and “[valid nonce]” with the value from the input “nonce” on the line that begins “var MEDIAFROMFTPIMPORT” on the page /wp-admin/admin.php?page=mediafromftp.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-ajax.php" method="POST">
<input type="hidden" name="action" value="mediafromftp-import-ajax-action" />
<input type="hidden" name="nonce" value="b90156c331" />
<input type="hidden" name="file" value="about.php" />
<input type="hidden" name="db_array" value="test" />
<input type="hidden" name="db_wp_attachment_metadata" value='O:20:"php_object_injection":0:{}' />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • September 11, 2017 – Developer notified.
  • September 11, 2017 – Developer responds.
  • Version 9.80 released, which fixes vulnerability.