Last Friday we had a pair of requests on one of our websites for a file from the plugin Backup & Restore Dropbox, /wp-content/plugins/dropbox-backup/template/css/tool-bar.css. Seeing as we never have had that plugin installed, that request would be likely a hacker probing for usage of the plugin. We could not find any previously disclosed vulnerabilities, so if there is a vulnerability that could exploited it looks to have not been previously disclosed.
While doing some basic checks through the code we found one fairly obvious issue, all of the plugin’s AJAX accessible functions lack a couple of standard security checks. More seriously they lacked any check on the what level of user was accessing them. When functions are registered through WordPress’ AJAX functionality they are normally accessible to anyone logged in to WordPress (there is also the option to make the available to those not logged in). Seeing as the plugin’s admin page is only accessible to Administrator level users, those AJAX functions should also limited as well. Without that quite a bit is accesible to lower level users. Most of the relevant functions are registered in the file /main/wpadm-class-wp.php:
add_action('wp_ajax_wpadm_local_restore', array('wpadm_wp_full_backup_dropbox', 'restore_backup') ); add_action('wp_ajax_wpadm_restore_dropbox', array('wpadm_wp_full_backup_dropbox', 'wpadm_restore_dropbox') ); add_action('wp_ajax_wpadm_logs', array('wpadm_wp_full_backup_dropbox', 'getLog') ); add_action('wp_ajax_wpadm_local_backup', array('wpadm_wp_full_backup_dropbox', 'local_backup') ); add_action('wp_ajax_wpadm_dropbox_create', array('wpadm_wp_full_backup_dropbox', 'dropbox_backup_create') ); add_action('wp_ajax_set_user_mail', array('wpadm_wp_full_backup_dropbox', 'setUserMail') ); add_action('wp_ajax_saveSetting', array('wpadm_wp_full_backup_dropbox', 'saveSetting') );
Based on that, a lower level user can create and restore backups, they also have the ability to view the logging from the plugin through the getLog() function. One of the things that function will show is were local backups are stored, but those backups are protected with .htaccess files, so unless the website is hosted on server that doesn’t use those (IIS and nginx being two prominent ones that don’t) you can’t access them directly.
Those functions also lack protection against cross-site request forgery (CSRF).
We would later find that the plugin has a PHP object injection vulnerability, which in all likelihood is what hackers are targeting.
Proof of Concept
The following proof of concept will display logged details of on local backups created through the plugin.
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="wpadm_logs" /> <input type="hidden" name="type-backup" value="local_backup" /> <input type="submit" value="Submit" /> </form> </body> </html>
- December 9, 2016 – Developer notified.
- December 15, 2016 – WordPress.org Plugin Directory notified.
- December 15, 2016 – Plugin removed from Plugin Directory.
- December 16, 2016 – Version 1.4.8, which fixes vulnerability, submitted to Plugin Directory repository.