11 Apr

100,000+ Install WordPress Plugin Marketed With Claim It Doesn’t Open Security Risks Has Persistent XSS Vulnerability

In monitoring the WordPress Support Forum for indications of vulnerabilities in plugins so that we can warn our customers of any publicly known security issues in plugins they use we have been seeing for sometime complaints about about problems with bogus signups on subscriber lists for newsletter plugins. It isn’t clear what the point of that would be or it is even intentional (if some knows what the explanation for that is please leave a comment). One of those plugins being, Email Subscribers & Newsletters, where someone began a topic seven weeks ago with this:

This plugin has been exploited by bots or scripts that dump a bunch of bogus Russian email addresses into the subscriber list. It was fixed once in a recent version, but was quickly exploited again. Until this is successfully resolved, I could not recommend the plugin because I have to disable it every time it is hacked.

That doesn’t really seem to describe exploitation or hacking.

The developer’s response isn’t great:

In Email Subscribers Free we have taken care of the majority of security issues.
But still, there could be a few ways that surpass our security measures.
To combat that, you could try out Email Subscribers Premium which had the CAPTCHA feature.
It helps achieve 100% security.
Hope this helps you.

A CAPTCHA seems like it would be the main solution against bots, so including that in the premium version seems problematic. The response to that from someone else seem to take things to far:

You are forcing people to buy premium subscription by using spammers. You can add Captcha to free plug-in as well. This is a security issue.
Congrats!

There have been two subsequent responses from the developer:

Hello,

We are working on fixing spam issue and will be available soon in ES 4.0..yeah..you heard it right. ES 4.0.

And:

Hi,

Just want to update you that we have fixed spam issue in ES 4.0.x

Hope that helps.

We ran across the latest response and went to look at what what was going and found that that there is reasonably serious security vulnerability in the sign up functionality and generally the plugin seems generally insecure. If someone wants an exhaustive security review of the plugin done, we offer just such a service for doing that.

Before we get into the details of that vulnerability it seems worth noting that the company behind the plugin specifically markets their plugins will not “open security risks”:

Great Code Quality
We care for our craft. Our plugins are lightweight yet powerful. They won’t slow your site down or open security risks. As a matter of fact, top developers have told us how impressed they are with our code quality!

In a better world a company would have at least the decency to not make that claim while not doing security basics, but this company hasn’t.

Vulnerability Details

The plugin handles the addition of subscribers through the function process_request() in the file /includes/admin/class-es-handle-subscription.php and that is accessed through WordPress’ AJAX functionality:

39
40
add_action( 'wp_ajax_es_add_subscriber', array( $this, 'process_request' ), 10 );
add_action( 'wp_ajax_nopriv_es_add_subscriber', array( $this, 'process_request' ), 10 );

The first code in that function appears to be the extent of the security. There is code trying limit the amount of requests that can come from an IP address, but that can easily bypassed since it relies on user input. There is also some attempt to validate what is submitted. That code is as follows:

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public function process_request() {
 
	$response = array( 'status' => 'ERROR', 'message' => '' );
 
	if ( ( isset( $_POST['es'] ) ) && ( 'subscribe' === $_POST['es'] ) && ! empty( $_POST['esfpx_es-subscribe'] ) ) {
 
		// Restrict too many requests
		$timeout = ES_Subscription_Throttaling::throttle();
		if ( $timeout > 0 ) {
			$response['message'] = 'es_rate_limit_notice';
			$this->do_response( $response );
			exit;
		}
 
		$form_data         = wp_unslash( $_POST );
		$validate_response = $this->validate_data( $form_data );
		if ( $validate_response['status'] === 'ERROR' ) {
 
			// We want to pretend as "SUCCESS" for blocked emails.
			// So, we are setting as "SUCCESS" even if this email is blocked
			if ( $validate_response['message'] === 'es_email_address_blocked' ) {
				$validate_response['status']  = 'SUCCESS';
				$validate_response['message'] = 'es_single_optin_success_message';
			}
 
			$this->do_response( $validate_response );
			exit;
		}

In between those two things something else stood out though. Here is that isolated:

$form_data         = wp_unslash( $_POST );

That code takes the user input that came with signup request and sets it to the variable $form_data without sanitizing it.

A quick check, as is shown with the proof of concept below, showed that malicious JavaScript code sent with a sign up request it isn’t sanitized down the line or escaped when output on at least one admin page, which is a persistent cross-site scripting (XSS) vulnerability. Vulnerabilities similar to that have been a recent target of hackers.

Due to the moderators of the WordPress Support Forum’s continued inappropriate behavior we are full disclosing vulnerabilities in protest until WordPress gets that situation cleaned up, so we are releasing this post and then only trying to notify the developer through the WordPress Support Forum. You can notify the developer of this issue on the forum as well. Hopefully the moderators will finally see the light and clean up their act soon, so these full disclosures will no longer be needed (we hope they end soon). You would think they would have already done that since multiple previously full disclosed vulnerabilities were quickly on hackers’ radar, but it appears those moderators have such disdain for the rest of the WordPress community that their continued ability to act inappropriate is more important that what is best for the rest of the community.

Proof of Concept

Place the short code for the default contact form that is created when you install the plugin on a page or post and then when not logged in to WordPress set the name value of the form to

"><script>alert(document.cookie);</script>

When visiting the Audience admin page, /wp-admin/admin.php?page=es_subscribers, an alert box with any available cookies will be shown.

Is It Fixed?

If you are reading this post down the road the best way to find out if this vulnerability or other WordPress plugin vulnerabilities in plugins you use have been fixed is to sign up for our service, since what we uniquely do when it comes to that type of data is to test to see if vulnerabilities have really been fixed. Relying on the developer’s information, can lead you astray, as we often find that they believe they have fixed vulnerabilities, but have failed to do that.


Concerned About The Security of the Plugins You Use?

When you are a paying customer of our service, you can suggest/vote for the WordPress plugins you use to receive a security review from us. You can start using the service for free when you sign up now. We also offer security reviews of WordPress plugins as a separate service.