WordPress 3 persistent script injection

From: Jouko Pynnonen <jouko@iki.fi>
To: bugtraq@securityfocus.com
Subject: WordPress 3 persistent script injection


A security flaw in WordPress 3 allows injection of JavaScript into
certain text fields. In particular, the problem affects comment boxes
on WordPress posts and pages. These don't require authentication by

The JavaScript injected into a comment is executed when the target
user views it, either on a blog post, a page, or in the Comments
section of the administrative Dashboard.

In the most obvious scenario the attacker leaves a comment containing
the JavaScript and some links in order to put the comment in the
moderation queue. The exploit is not then visible to normal users,
search engines, etc.

When a blog administrator goes to the Dashboard/Comments section to
review new comments, the JavaScript gets executed. The script can then
perform operations with administrator privileges.

For instance, our PoC exploits first clean up traces of the injected
script from the database, then perform other administrative tasks such
as changing the current user's password, adding a new administrator
account, or using the plugin editor to write attacker-supplied PHP
code on the server (this impact applies to any WordPress XSS if
triggered by an administrator).

These operations happen in the background without the user seeing
anything out of ordinary.

If the attacker writes new PHP code on the server via the plugin
editor, another AJAX request can be used to execute it
instantaneously, whereby the attacker gains operating system level
access on the server.

The exploit will NOT be triggered directly at the Dashboard "root
view" because only snippets (20 first words) of the latest comments
are shown there with all HTML stripped.

If approved there, the exploit will be triggered by any user viewing
the targeted blog posting or page, with their corresponding

Plugins that let unprivileged users to enter HTML text may offer other
attack vectors.


WordPress allows a few HTML tags in comments, such as the anchor <A>,
bold <B>, and code <CODE> tags. Certain white-listed attributes are
allowed in each tag. Obviously, the "href" attribute is important for
anchor tags, but e.g. the "onmouseover" attribute would be

The problem occurs in a text formatting function called wptexturize()
which is normally executed for each comment and other blocks of text.
The function replaces certain simple characters with fancier HTML
entities. For instance, straight quote symbols are replaced with
opening and closing curly quotes, unicode 8220 and 8221.

In order to avoid interfering with HTML formatting, wptexturize()
first splits the text in segments. The splitting is expected to pick
HTML tags (which aren't texturized) apart from running text (which is

In addition to HTML tags, the code is supposed to recognize
square-bracketed shortcodes such as [CODE] and avoid texturizing them.

The splitting is implemented with a regular expression in

   $textarr = preg_split('/(<.*>|\[.*\])/Us', $text, -1,

A text containing carefully mixed square and angle brackets confuses
the splitting process and results in HTML code getting partially

An attacker can exploit the bug to supply any attributes in the
allowed HTML tags. A style attribute can be used to create a
transparent tag covering the whole window, forcing the execution of
its onmouseover handler.

In practical applications the script would probably first remove the
transparent tag to avoid interfering with UI events and re-triggering
the handler. It could then insert a new <SCRIPT> tag to load a more
complex JavaScript file to execute from another web server. This
script can use e.g. jQuery to chain AJAX operations for posting HTML
forms and retrieving the required nonces.


We tested a few WordPress versions from 3.0 to the latest 3.9.2. All
tested versions were vulnerable. The problem seems to have gone
uncorrected for almost four years.

Version 4.0 uses a different kind of regular expression and is NOT
vulnerable to this problem.


Texturizing can be easily disabled by adding a return statement in the
beginning of the function in wp-includes/formatting.php:

  function wptexturize($text) {
        return $text;                  // ADD THIS LINE
        global $wp_cockneyreplace;

This changes how some punctuation marks look like but the difference
is quite minor.

We have also made a WordPress plugin available for disabling
texturization. For more information and an up-to-date version of this
document, please refer to our website http://klikki.fi

The preferred solution should be applying the official patch released
by WordPress.


WordPress was notified on September 26 and has released patches
correcting the problem. The WordPress security advisory is available



The vulnerability was discovered and researched by Jouko Pynnonen,
Klikki Oy, Finland.

Jouko Pynnonen <jouko@iki.fi>
Klikki Oy - http://klikki.fi

Copyright © 1995-2020 LinuxRocket.net. All rights reserved.