Updated March 20: added some technical details and YouTube demo.
Google Analytics by Yoast is a WordPress plug-in for monitoring website traffic. With approximately seven million downloads it’s one of the most popular WordPress plug-ins.
Despite the code being regularly audited since 2014, the exposed vulnerability is critcal and apparently the most serious vulnerability ever disclosed in the Yoast WordPress plug-ins.
It is relatively easy for an attacker to execute server-side code by exploiting this vulnerability. Under default WordPress configuration, a malicious user can use this flaw to write PHP files on the server via the plugin or theme editors (see the YouTube example).
Alternatively the attacker could change the administrator’s password, create new administrator accounts, or do whatever else the currently logged-in administrator can do on the target site.
The bug was found by Klikki Oy in late February but the full impact didn’t become clear until a more detailed investigation in March. There is now an update available correcting the issue.
The impact is a combination of two underlying problems. Firstly, missing access control allows an unauthenticated user to modify some of the settings associated with the plug-in. It’s possible overwrite the existing OAuth2 credentials which the plug-in uses for retrieving data from Google Analytics, and thereby connect the plug-in with the attacker’s own Google Analytics account.
Secondly, the plug-in renders an HTML dropdown menu based on the data downloaded from Google Analytics. This data is not sanitized or HTML-escaped. If the said attacker enters HTML code such as <script> tags in the properties in their Google Analytics account settings, it will appear in the WordPress administrative Dashboard of the targeted system and get executed whenever someone views the settings.
Proof of Concept
The following HTML snippet could be used to hijack the Google Analytics account of a website running a vulnerable version of the plug-in:
<a href="http://YOUR.BLOG/wp-admin/admin-post.php?reauth=1">reauth</a> <br><br> <form method=POST action="http://YOUR.BLOG/wp-admin/admin-post.php"> <input type=text size=100 name="google_auth_code"> <input type=submit> </form>
First, the attacker would click the reauth link. The action doesn’t require any kind of authentication. It will reset some of the plugin settings and redirect the attacker to a google.com OAuth dialog, where they’d get an authentication code.
Next the attacker would copy-paste the code in the above form and submit. This would update the code in the plugin settings – again without requiring authentication. The plugin would now retrieve its data from the attacker’s Google Analytics account.
The actual payload script would be entered at the attacker’s own Google Analytics account settings at https://www.google.com/analytics/web/?hl=en#management/Settings/
An example of a property name:
This would fire an alert box whenever an administrator views the Analytics settings page in the Dashboard of the target WordPress site.
A real-world attack would probably use a src attribute to load a more sophisticated script from an external site. It could make chained ajax calls to load and submit administrative forms, including those of the plugin editor to write server-side PHP code, and finally execute it.
Yoast was notified on March 18, 2015. A new version of the plug-in (5.3.3) was released the next day.
The vulnerability was the sixth discovered in February 2015 by Jouko Pynnönen of Klikki Oy while investigating websites in the scope of Facebook’s bug bounty program. The bug, like the previous ones, were revealed when inspecting the detected WordPress plug-ins with PHP Multipass, our code analysis tool.
The previously reported vulnerabilities include four bugs in the WPML translation plug-in. In September 2014, Klikki Oy detected a critical stored XSS in the WordPress core affecting about 90% of all WordPress sites. In November we discovered another WordPress core vulnerability with a similar impact. It affects all versions from 3.0 (possibly earlier) to 4.2 beta and is unresolved at the time of writing.