Persistent Cross-Site Scripting (XSS) Vulnerability in Post Custom Templates Lite
Unlike most companies providing security services related to WordPress we are interested improving the security of the WordPress ecosystem, so that the average website isn’t required to use any security product or service. That isn’t easy since even the people on the WordPress side of things too often don’t seem interested in that. One new way that we are trying to improve security is by catching serious vulnerabilities in WordPress plugins when they are included in a new version of the plugin (if we had more customers we could expand this to less serious vulnerabilities).
Through that we have already found a number of lesser vulnerabilities that came up in the course of looking into potential instances of the more serious vulnerabilities. So far many of those haven’t been fixed, so those using the plugins would want to be using a service or plugin that notifies of vulnerable plugins to aware of the problem. While there a number of those, from our checking the other ones have not included those vulnerabilities or many of the others we have disclosed, so that is where our service provides you something you can’t get elsewhere (those other data source are missing many recently disclosed vulnerabilities disclosed by others as well).
In a troubling reminder of the poor state of the security of WordPress plugins, often the lesser vulnerabilities we have found are due to rather glaring security problems. That was case with the plugin Post Custom Templates Lite, where in looking into a potential arbitrary file upload vulnerability we found that it was possible for anyone to take actions that are only intended for Administrator-level users.
When the plugin is active it causes WordPress to run the plugin’s function otw_pctl_init() as WordPress loads (in the file /otw_post_custom_templates_lite.php):
80 | add_action('init', 'otw_pctl_init', 10000 ); |
The last line of the function otw_pctl_init() causes the file that handles requests to the plugin’s admin actions to run (in the file /include/otw_pctl_functions.php):
101 | include_once( 'otw_pctl_process_actions.php' ); |
Before doing any of those actions there should be a check to make sure the request is coming from an Administrator and that there is a valid to nonce to protect against cross-site request forgery (CSRF). Instead the only check was if the request includes the POST input “otw_pctl_action”, which indicates which action should be taken (in the file /include/otw_pctl_process_actions.php):
6 | if( isset( $_POST['otw_pctl_action'] ) ){ |
It looks like the most serious issue that could have come out of this at this time was persistent cross-site scripting (XSS) due to the ability to change the plugin’s settings, but if it hadn’t been caught now then down the road actions that have more consequence could have been added and left unprotected.
After we notified the developer of the problem they released version 1.7, which adds a capabilities check before allow accessing to the admin functions:
6 | if( isset( $_POST['otw_pctl_action'] ) && current_user_can( 'manage_options' ) ){ |
It also adds proper protection against CSRF.
Proof of Concept
The following proof of concept will cause any available cookies to be shown in an alert box when visiting the page /wp-admin/admin.php?page=otw-pctl-settings.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/" method="POST"> <input type="hidden" name="otw_pctl_action" value="manage_otw_pctl_options" /> <input type="hidden" name="otw_pctl_custom_css" value="</textarea><script>alert(document.cookie);</script>" /> <input type="submit" value="Submit" /> </form> </body> </html>
Timeline
- June 28, 2017 – Developer notified.
- June 29, 2017 – Developer responds.
- July 2, 2017 – Version 1.7 released, which fixes vulnerability.