20 Oct

Authenticated Information Disclosure Vulnerability in Duplicate Page

We recently went to a take a look at the details of a reflected cross-site scripting (XSS) vulnerability that had been disclosed in the plugin Duplicate Page we noticed that it also had a cross-site request forgery (CSRF) vulnerability. After that we remember that a similar plugin Duplicate Post had previously had a vulnerability that allowed lower level users to get access to password protected posts by duplicating them that was in part due to a lack of protection against CSRF and we then went to check if that was issue with that plugin as well. We found that it was possible.

With the other plugin its functionality was only intended to be used by Editor and Administrator-level users, while with this one the plugin ads links to do the duplication as long as the user has the “edit_posts” capability (in the file /duplicatepage.php):

178
179
180
if (current_user_can('edit_posts')) {
$actions['duplicate'] = '<a title="Duplicate this as '.$post_status.'" href="admin.php?action=dt_duplicate_post_as_draft&post=' . $post->ID . '" rel="permalink">'.__( "Duplicate This", "duplicate_page" ).'</a>';
}

That normally is available to contributor-level and above users.

The duplication is handled by the function dt_duplicate_post_as_draft(), which is accessible to anyone logged in because it is registered as an admin_action:

23
add_action( 'admin_action_dt_duplicate_post_as_draft', array(&$this,'dt_duplicate_post_as_draft') );

That function doesn’t perform any checks as to who is making the request, so anyone that is logged in can duplicate any post. Normally only contributor-level and above could then view the resulting post since it is stored as a draft by default. Through that they could gain access to the contents of posts they would normally not have access to, including password protected posts.

We notified the developer of other security issues in the plugin through their website on October 4 and planned to mention this once they responded, but they didn’t respond. We then notified them of this through the email address listed on the plugin’s page on wordpress.org on October 13, as well as mentioning the previous issues again. We have yet to hear back from them and a new version has not been released. 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

Log in to WordPress as a contributor-level user and visiting the following URL, with the value of “[path to WordPress]” replaced with the location of WordPress and  “[post ID]” replaced with the value of a password protected post on the website:

http://[path to WordPress]/wp-admin/admin.php?action=dt_duplicate_post_as_draft&post=[post ID]

You will now be able to view the contents of the post without having to enter a password.

Timeline

  • October 13, 2017 – Developer notified.
19 Sep

Authenticated Information Disclosure Vulnerability in Share Drafts Publicly

The changelog entry for version 1.1.4 of Share Drafts Publicly is “Added security enhancements.”. In looking over that we found a change was made to fix a cross-site request forgery (CSRF) vulnerability that existed with AJAX functionality to share a draft of a post or page publicly. The exploitability of that is limited since an attacker that causes a draft to be shared publicly would still have to guess a 6 character secret key generated using wp_generate_password() to be able to view the draft.

With a CSRF vulnerability you cannot see the result of the request because it is being made by someone else, but the response to the request here does return the secret key needed to view the draft, so there was the potential that WordPress users that don’t have access to a draft could use the functionality to view it since the AJAX request was accessible to anyone logged in to WordPress. In version 1.1.3 we found that anyone logged in could make any draft public. In looking at the changes made in 1.1.4, we found there was no change to deal with that issue.

In version 1.1.4 because of the new CSRF protection, a user would now need to have access to a valid nonce to be able to make a draft public.

The nonce is generated in the function scripts(), which is called when enqueueing admin scripts (in the file /share-drafts-publicly.php):

52
add_action( 'admin_enqueue_scripts', array( $this, 'scripts' ) );

The function will include the nonce when the function enqueue_script() is true:

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
public function scripts() {
 
	// Localize strings.
	$localization = array(
		'nonce'  => wp_create_nonce( 'share-drafts-publicly' ),
		'postId' => get_the_ID() ? get_the_ID() : ( isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0 ),
	);
 
	wp_register_script( 'share-drafts-publicly', plugin_dir_url( __FILE__ ) . 'js/share-drafts-publicly.js', array( 'jquery' ), filemtime( plugin_dir_path( __FILE__ ) . 'js/share-drafts-publicly.js' ), true );
	wp_localize_script( 'share-drafts-publicly', 'shareDraftsPublicly', $localization );
 
	if ( $this->enqueue_script() ) {
		wp_enqueue_script( 'share-drafts-publicly' );
	}
 
}

That returns true when on the page /wp-admin/post.php:

120
121
122
123
124
125
126
127
public function enqueue_script() {
 
	// Get current page.
	global $pagenow;
 
	return 'post.php' === $pagenow;
 
}

So as long as a user can visit the page /wp-admin/post.php they would now be able to make any draft public. Without any plugins making something using that page available to lower level users, only users at the Contributor-level or above could get access to the nonce normally.

Less than an hour after we notified the developer of the issue they released version 1.1.5, which fixed the issue by adding the following code to the beginning of the functions make_draft_public() and make_draft_private():

if ( ! current_user_can( 'edit_posts', $post_id ) ) {
	return false;
}

That makes sure the user trying to make a draft public or private is able to edit it.

Proof of Concept

When logged in as a user that has access to some URL that uses /wp-admin/post.php, visiting the following URL will make the specified draft public.

Make sure to replace “[path to WordPress]” with the location of WordPress, “[post ID]” with the ID of the draft post you want to make public, and “[valid nonce] with a valid nonce that can be found on the URL that uses /wp-admin/post.php on the line that begins “var shareDraftsPublicly”.

http://[path to WordPress]/wp-admin/admin-ajax.php?action=share_drafts_publicly&make=public&post_id=[post ID]&nonce=[valid nonce]

Timeline

  • September 18, 2017 – Developer notified.
  • September 18, 2017 – Version 1.1.5 released, which fixes issue.
  • September 18, 2017 – Developer responds.
24 Aug

Authenticated Information Disclosure Vulnerability in Advanced Contact form 7 DB

One of the strengths of WordPress is the multitude of plugins available, if you need some functionality you are likely to find a plugin that provides it. There are downsides as well. With over 51,000 plugins in the Plugin Directory it isn’t surprising to find new plugins that duplicate functionality already provided by another plugin. One of the downsides of that is that we have seen a fair amount of situations where a vulnerability has been fixed in a plugin and then another similar plugin comes along that has that same vulnerability. In the case of a vulnerability we found in the plugin Advanced Contact form 7 DB, we found the same vulnerability we had found in a couple of other similar plugins. The vulnerabilities in the other plugin still haven’t been fixed, while this one has now been fixed, though you wouldn’t know that there was a security fix in the version that fixed it if you relied on the plugin’s changelog.

The plugin entered our radar when a piece of its code showed got flagged as part of our proactive monitoring for serious vulnerabilities in WordPress plugins. The code in question turned out to not be vulnerable, but based on the vulnerabilities we had found in similar plugins, which allowed people that shouldn’t be able to view the contents of contact form submissions, we checked to see if it was also an issue with this plugin and it turned out to be the case.

The plugin makes the function vsz_cf7_edit_form_ajax() available through WordPress’ AJAX functionality to anyone logged in to WordPress (in the file /includes/class-advanced-cf7-db.php):

194
$this->loader->add_action('wp_ajax_vsz_cf7_edit_form_value',$plugin_admin, 'vsz_cf7_edit_form_ajax');

The function vsz_cf7_edit_form_ajax(), in the file /admin/class-advanced-cf7-db-admin.php, will return the contents of a specified contact form submission:

699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
public function vsz_cf7_edit_form_ajax(){
	global $wpdb;
	//Check entry id set or not in current request
	$rid = ((isset($_POST['rid']) && !empty($_POST['rid'])) ? intval($_POST['rid']) : '');
	//If entry not empty 
	if(!empty($rid)){
		//Get entry related all fields information 
		$sql = $wpdb->prepare("SELECT * FROM ".VSZ_CF7_DATA_ENTRY_TABLE_NAME." WHERE `data_id` = %d", $rid);
		$rows = $wpdb->get_results($sql);
		$return = array();
		//Set all fields name in array
		foreach ($rows as $k => $v) {
			$return[$v->name] = html_entity_decode(stripslashes($v->value));
		}
		//All fields encode in JSON format and return in AJAX request
		exit(json_encode($return));
	}
}

The page that requests to that are intended to come from is limited to those with the “manage_options” capability, which would normally be Administrator-level users. The code in the function didn’t perform any check on what level of user is making the request.

Also worth noting is that the code is nearly identical to the vulnerable code in the plugin Contact Form 7 Database, yet there is no mention of the other developer in the copyright section of the plugin.

After we notified the developer of the issue the plugin was changed so that the first thing that happens in the function vsz_cf7_edit_form_ajax() is check to make sure the user has the “manage_option” capability:

700
701
public function vsz_cf7_edit_form_ajax(){
	if(!current_user_can( 'manage_options' )) return;

The changelog entries for the new version, 1.1.1, make no mention of a security fix being included:

  • Made changes to resolve issue of user feasibility when editing the form fields.
  • Minor tweak related to export functionality and attachment download functionality

Proof of Concept

The following proof of concept will show the first saved contact form submissions, when logged in to WordPress.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-ajax.php" method="POST">
<input type="hidden" name="action" value="vsz_cf7_edit_form_value" />
<input type="hidden" name="rid" value="1" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • August 21, 2017 – Developer notified.
  • August 24, 2017 – Version 1.1.1 released, which fixes vulnerability.
09 Aug

Authenticated Information Disclosure Vulnerability in Cherry Team Members

The plugin Cherry Team Members had the same authenticated information disclosure that the Cherry Services List had. The vulnerability was caused by the fact that  contributor and author level users could duplicate posts that they would not have been able to edit. That could for example, have allowed them to gain access to the contents of password protected posts.

The plugin makes the function duplicate_post_as_draft() available to anyone logged in through the admin_action action (in the file /admin/includes/class-cherry-team-admin-columns.php):

41
add_action( 'admin_action_cherry_team_clone_post', array( $this, 'duplicate_post_as_draft' ) );

The only restriction that the plugin placed on accessing that function’s code and duplicating a post as of version 1.4.1 is that the user has the edit_posts capability, which is normally possessed by contributor level and above users:

84
85
86
87
88
function duplicate_post_as_draft() {
 
	if ( ! current_user_can( 'edit_posts' ) ) {
		wp_die( 'You don\'t have permissions to do this' );
	}

After we notified the developer of the plugin of the issue, version 1.4.2 was released, which fixes the vulnerability by checking if the user has the capability to edit the post being duplicated:

102
103
104
if ( ! current_user_can( 'edit_post', $_REQUEST['post'] ) ) {
	wp_die( 'You don\'t have permissions to do this' );
}

Proof of Concept

Log in to WordPress as a contributor-level user and visiting the following URL, with the value of “[path to WordPress]” replaced with the location of WordPress and  “[post ID]” replaced with the value of a password protected post on the website:

http://[path to WordPress]/wp-admin/admin.php?action=cherry_team_clone_post&post=[post ID]

Timeline

  • August 8, 2017 –  Developer notified.
  • August 9. 2017 – Version 1.4.2 released, which fixes vulnerability.
09 Aug

Authenticated Information Disclosure Vulnerability in Cherry Services List

While looking into a possible expansion of what we check during our security review of WordPress plugins  chosen by our customers we found that the plugin Cherry Services List had an authenticated information disclosure vulnerability. That was caused by the fact that contributor and author level users could duplicate posts that they would not have been able to edit. That could for example, have allowed them to gain access to the contents of password protected posts.

The plugin makes the function duplicate_post_as_draft() available to anyone logged in through the admin_action action (in the file /admin/includes/class-cherry-services-meta.php):

41
add_action( 'admin_action_cherry_services_clone_post', array( $this, 'duplicate_post_as_draft' ) );

The only restriction that the plugin placed on accessing that function’s code and duplicating a post as of version 1.4.1 is that the user has the edit_posts capability, which is normally possessed by contributor level and above users:

85
86
87
88
89
function duplicate_post_as_draft() {
 
	if ( ! current_user_can( 'edit_posts' ) ) {
		wp_die( __( 'You don\'t have permissions to do this', 'cherry-services' ) );
	}

After we notified the developer of the plugin of the issue, version 1.4.2 was released, which fixes the vulnerability by checking if the user has the capability to edit the post being duplicated:

104
105
106
if ( ! current_user_can( 'edit_post', $_REQUEST['post'] ) ) {
	wp_die( 'You don\'t have permissions to do this!', 'cherry-services' );
}

Proof of Concept

Log in to WordPress as a contributor-level user and visiting the following URL, with the value of “[path to WordPress]” replaced with the location of WordPress and  “[post ID]” replaced with the value of a password protected post on the website:

http://[path to WordPress]/wp-admin/admin.php?action=cherry_services_clone_post&post=[post ID]

Timeline

  • August 8, 2017 –  Developer notified.
  • August 9. 2017 – Version 1.4.2 released, which fixes vulnerability.
08 Jun

Authenticated Information Disclosure Vulnerability in Contact Form 7 Database

After noticing that another plugin that saves contact form submissions from the plugin Contact Form 7 made them publicly accessible we took a look other plugins that also save them to see if any of them had a similar issue. In doing that we found that the plugin Contact Form 7 Database made saved contact form submissions available to anyone logged in to WordPress.

The plugin makes the function cf7d_edit_value_ajax_func() available to those logged in, through WordPress’ AJAX functionality (in the file /admin/edit-value.php):

74
add_action('wp_ajax_cf7d_edit_value', 'cf7d_edit_value_ajax_func');

That function doesn’t perform any check as to the user role or capability before providing them with the content of a specified saved contact form submission:

75
76
77
78
79
80
81
82
83
84
85
86
function cf7d_edit_value_ajax_func()
{
    global $wpdb;
    $rid = ((isset($_POST['rid'])) ? (int)$_POST['rid'] : '');
    if (!empty($rid)) {
        $sql = $wpdb->prepare("SELECT * FROM ".$wpdb->prefix."cf7_data_entry WHERE `data_id` = %d", $rid);
        $rows = $wpdb->get_results($sql);
        $return = array();
        foreach ($rows as $k => $v) {
            $return[$v->name] = stripslashes($v->value);
        }
        exit(json_encode($return));

By comparison the page where that AJAX requests is made from by the plugin is limited to those with the manage_option capability, which using only Administrator-level users have (in the file /admin/init.php):

20
$menu = add_submenu_page('wpcf7', 'Database', 'Database', 'manage_options', 'cf7-data', 'cf7d_custom_submenu_page_callback');

When we notified the company behind the plugin of the vulnerability over a month ago and they responded “Our developers working to fix it.”, but the vulnerability has yet to be fixed.

Proof of Concept

The following proof of concept will show the first saved contact form submissions, when logged in to WordPress.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-ajax.php" method="POST">
<input type="hidden" name="action" value="cf7d_edit_value" />
<input type="hidden" name="rid" value="1" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • May 3, 2017 – Developer notified.
  • May 3, 2017 – Developer responds.
10 Apr

Vulnerability Details: Authenticated Information Disclosure Vulnerability in Duplicate Post

From time to time vulnerabilities are fixed in plugin without someone putting out a report on the vulnerability and we will put out a post detailing the vulnerability. While putting out the details of the vulnerability increases the chances of it being exploited, it also can help to identify vulnerabilities that haven’t been fully fixed (in some cases not fixed at all) and help to identify additional vulnerabilities in ...


To read the rest of this post you need to have an active account with our service.

For existing customers, please log in to your account to view the rest of the post.

If you are not currently a customer, when you sign up now you can try the service for free for the first month (there are a lot of other reason that you will want to sign up beyond access to posts like this one).

If you are a security researcher please contact us to get free access to all of our Vulnerability Details posts.

15 Dec

Authenticated Information Disclosure Vulnerability in Backup & Restore Dropbox

Last Friday we had a pair of requests on one of our websites for a file from the plugin Backup & Restore Dropbox, /wp-content/plugins/dropbox-backup/template/css/tool-bar.css. Seeing as we never have had that plugin installed, that request would be likely a hacker probing for usage of the plugin. We could not find any previously disclosed vulnerabilities, so if there is a vulnerability that could exploited it looks to have not been previously disclosed.

While doing some basic checks through the code we found one fairly obvious issue, all of the plugin’s AJAX accessible functions lack a couple of standard security checks. More seriously they lacked any check on the what level of user was accessing them. When functions are registered through WordPress’ AJAX functionality they are normally accessible to anyone logged in to WordPress (there is also the option to make the available to those not logged in). Seeing as the plugin’s admin page is only accessible to Administrator level users, those AJAX functions should also limited as well. Without that quite a bit is accesible to lower level users. Most of the relevant functions are registered in the file /main/wpadm-class-wp.php:

 add_action('wp_ajax_wpadm_local_restore', array('wpadm_wp_full_backup_dropbox', 'restore_backup') );
 add_action('wp_ajax_wpadm_restore_dropbox', array('wpadm_wp_full_backup_dropbox', 'wpadm_restore_dropbox') );
 add_action('wp_ajax_wpadm_logs', array('wpadm_wp_full_backup_dropbox', 'getLog') );
 add_action('wp_ajax_wpadm_local_backup', array('wpadm_wp_full_backup_dropbox', 'local_backup') );
 add_action('wp_ajax_wpadm_dropbox_create', array('wpadm_wp_full_backup_dropbox', 'dropbox_backup_create') );
 add_action('wp_ajax_set_user_mail', array('wpadm_wp_full_backup_dropbox', 'setUserMail') );

 add_action('wp_ajax_saveSetting', array('wpadm_wp_full_backup_dropbox', 'saveSetting') );

Based on that, a lower level user can create and restore backups, they also have the ability to view the logging from the plugin through the getLog() function. One of the things that function will show is were local backups are stored, but those backups are protected with .htaccess files, so unless the website is hosted on server that doesn’t use those (IIS and nginx being two prominent ones that don’t) you can’t access them directly.

Those functions also lack protection against cross-site request forgery (CSRF).

We would later find that the plugin has a PHP object injection vulnerability, which in all likelihood is what hackers are targeting.

Proof of Concept

The following proof of concept will display logged details of on local backups created through the plugin.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-ajax.php" method="POST">
<input type="hidden" name="action" value="wpadm_logs" />
<input type="hidden" name="type-backup" value="local_backup" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • December 9, 2016 – Developer notified.
  • December 15, 2016 – WordPress.org Plugin Directory notified.
  • December 15, 2016 – Plugin removed from Plugin Directory.
  • December 16, 2016 – Version 1.4.8, which fixes vulnerability, submitted to Plugin Directory repository.
03 Aug

Authenticated Information Disclosure Vulnerability in Simple History

One of things we do to keep track of what vulnerabilities are being discovered in WordPress plugins is to monitor the WordPress support forums for threads related to plugin vulnerabilities. In addition to picking up the type of information we are looking for, we see an assortment of threads about security issues. One that we saw recently involved some one requesting that WordPress include the ability to log user activity, a “Support Representative” pointed them to a couple of plugins that do that. In response the original poster mentioned they were concerned about the additional security risk of the plugins:

I’ve been told by our web developer that keeping plugins to a minimum is the smartest route security-wise. Since these are not official WordPress plugins and don’t have very many ratings, would it increase or decrease the security of my websites to install one of them?

What we found interesting about this was that both of the logging plugins that had been mentioned were ones that we had recently found minor security issues with, so the potential of them introducing an additional security risk was not hypothetical. That doesn’t mean that you shouldn’t use logging plugins or other plugins, but it is a reminder that even plugins with a security purpose can introduce security risks.

Those two plugins were not the only logging plugins we have security issues with and we have now found another one that contained a security issue.

One frequent source of security issues being discovered these days is lack of proper restriction on who can access in functions that are made accessible through WordPress’ AJAX functionality. By default those functions are accessible to anyone who is logged in to WordPress, even though the functions are often intended to only accessible to high level users. For many websites where there is only a single Administrator account or small amount of trusted users these vulnerabilities don’t pose a risk, but for plugins that are intended to be used in environments where that isn’t the case it is more of a concern. That brings us to one such plugin, Simple History, which logs user activity.

In looking over that plugin we found that in the then current version, 2.7.4, a number of functions were available to anyone who is logged in. That included the function api(), which returns the data displayed on the plugin’s page, so anyone who is logged in can see everything that is logged. (Update 8/9/2016: While this function is accessible to anyone, there is actually a restriction in place elsewhere in the code that prevents access to it from allow unauthorized access to data through this.). It also included the function ajax_simple_history_filters_search_user(), which along with providing what was logged for a specified user, also displays some of the user’s details, including their email address.

After we notified the developer of the issue, version 2.7.5 was released that fixes the issue by adding a capability check to relevant functions:

// user must have list_users capability (default super admin + administrators have this)
if ( ! current_user_can("list_users") ) {
	wp_send_json_error();;
}

As reminder that you can’t rely on a plugin’s changelog to tell you whether a security issue has been fixed, the changelog entry for 2.7.5 makes no mention of any included security fix:

  • User logins using e-mail are now logged correctly. Previously the user would be logged in successfully but the log said that they failed.
  • Now only users with list_users capability can view the users filter and use the autocomplete api for users.
  • Add labels to search filters. (I do really hate label-less forms so it’s kinda very strange that this was not in place before.)
  • Misc other internal fixes

Proof of Concept

The following proof of concept will display a user’s details, including their email address.

Make sure to replace “[path to WordPress]” with the location of WordPress and “[username]” of the users you want to see the details of.

http://[path to WordPress]/wp-admin/admin-ajax.php?q=[username]&page_limit=10&action=simple_history_filters_search_user

Timeline

  • 7/28/2016 – Developer notified.
  • 7/30/2016 – Developer responds.
  • 8/3/2016 – Version 2.7.5 released, which fixes issue.
11 Jul

Protecting You Against Wordfence’s Bad Practices: Information Disclosure Vulnerability in WP Maintenance Mode

Wordfence is putting WordPress website at risk by disclosing vulnerabilities in plugins with critical details needed to double check their work missing, in what appears to be an attempt to profit off of these vulnerabilities. We are releasing those details so that others can review the vulnerabilities to try to limit the damage Wordfence’s practice could cause.

Wordfence describes the information disclosure vulnerability in WP Maintenance Mode version 2.0.6 as “allows a remote attacker to download the list of subscribers from WP Maintenance Mode who have asked to be notified when a site returns to full functionality. To exploit this vulnerability, an attacker simply needs to have a registered account on the victim site with no special permissions.”.

First off, most WordPress website don’t allow the public to create accounts, so saying the attacker “simply needs to have a registered account on the victim site” seems to be misleading at best.

When we went to look for the vulnerability we had a pretty good idea of where it should be, as with this type of issue usually there is a function accessible through AJAX that does not contain the proper checks to make only those intended to access it can. In version 2.0.6 of the plugin, in the file /includes/classes/wp-maintenance-mode-admin.php, we found what seemed to be the relevant function being registered for AJAX access:

41
add_action('wp_ajax_wpmm_subscribers_export', array($this, 'subscribers_export'));

But the connected function was already checking to make sure that lower level users could not access the function by exiting if the user cannot manage_options, which only Administrator level users normally have access to:

117
118
119
120
121
122
123
124
125
126
public function subscribers_export() {
	global $wpdb;
 
	try {
		// check capabilities
		if (!current_user_can('manage_options')) {
			throw new Exception(__('You do not have access to this resource.', $this->plugin_slug));
		}
 
		// get subscribers and export

At that point we went looking for something else that could do this particular export and came up empty. Looking at the changes made between 2.0.6 and 2.0.7 didn’t show any changes that would match this vulnerability. We then went back and found the code that checks the user’s capability was added in version 2.0.4. You can see that in version 2.0.3, the function’s code starts without any check first:

104
105
106
107
public function subscribers_export() {
	global $wpdb;
 
	$results = $wpdb->get_results("SELECT email, insert_date FROM {$wpdb->prefix}wpmm_subscribers ORDER BY id_subscriber DESC", ARRAY_A);

Not only did Wordfence claim the vulnerability was in version 2.0.6, which it wasn’t, but they claimed they notified the developer of the vulnerabilities in the week of June 26 – July 2. Version 2.0.4 was released on June 16, so something is not right here.

Proof of Concept

The following proof of concept will download the subscriber list, when logged in to WordPress.

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

http://[path to WordPress]/wp-admin/admin-ajax.php?action=wpmm_subscribers_export