Mostly code, sometimes beer

…and some netsec too

Stored XSS Vulnerability in the WordPress Plugin Subscribe2

The Subscribe2 plugin’s shortcode signup form stores the user’s IP address in a hidden form field:

Lines 117 and 119 of class-s2-frontend.php

$this->form = ..."><input type=\"hidden\" name=\"ip\" value=\"" . $_SERVER['REMOTE_ADDR'] . "\" />"...

When the form is submitted the hidden IP input is stored in the wp_subscribe2.ip column when the user first subscribes (only the first time, when they are confirmed the IP column is replaced with value of $_SERVER['REMOTE_ADDR']). The IP is then output onto the page of the subscriber list in the WordPress admin panel unescaped in the title attribute of the abbr tag:

Line 41 of class-s2-list-table.php

return sprintf('<span style="color:#FF0000"><abbr title="' . $mysubscribe2->signup_ip($item['email']) . '">%1$s</abbr></span>', $item['email']);

An attacker can replace the value of the hidden ‘ip’ input with something like this:

"><script src=></script>

The payload needs to fit within the 64 character limit on the wp_subscribe2.ip column with the database, and is run through addslashes, but the external script will load and run.

Usually XSS attacks are low to moderate severity since they are usually used as more ‘targeted’ attacks (you need to actually get an admin to click a link, etc), but this is passive and fairly easy to automate. An attacker can simply scrape WordPress sites looking for the form and submit the XSS payload, which will run the next time an admin looks at the subscriber logs. The subscriber list is also sorted alphabetically so the attacker can use (or something like that) and have their email address appear first in the list.

Subscribe2’s developers were quick to respond and pushed out an update 5 days from the initial discovery. Subscribe2 stands at 1.4 million downloads at the time of writing.