12 Oct

Vulnerability Details: Reflected Cross-Site Scripting (XSS) Vulnerability in WP Editor

From time to time vulnerabilities are fixed in plugin without someone putting out a report on the vulnerability and we will put out a post detailing the vulnerability. While putting out the details of the vulnerability increases the chances of it being exploited, it also can help to identify vulnerabilities that haven’t been fully fixed (in some cases not fixed at all) and help to identify additional vulnerabilites in the plugin.

Our first vulnerability details post was rather cut and dry, as it was easy to determine what the vulnerability was and confirm it existed. For our second it turned that some of the security changes made that related to described vulnerability in the changelog do not look to have been exploitable, so if those were the only changes there wouldn’t have been a vulnerability to add to our data.

Stepping back a bit, the only changelog entry for version of the plugin WP Editor is “Fixed multiple XSS vulnerabilities”. Looking at the changes made in the release you can see that user input in several locations has been run through the function esc_html(), which escapes it.

That occurs in several places in the function save_settings(), which is located in the file /classes/WPEditorAjax.php. Before the lines where the escaping has occurred though there is a cross-site request forgery (CSRF) check done:

if ( ! check_ajax_referer( 'wp_editor_ajax_nonce_settings_main', 'wp_editor_ajax_nonce_settings_main', false ) && ! check_ajax_referer( 'wp_editor_ajax_nonce_settings_themes', 'wp_editor_ajax_nonce_settings_themes', false ) && ! check_ajax_referer( 'wp_editor_ajax_nonce_settings_plugins', 'wp_editor_ajax_nonce_settings_plugins', false ) && ! check_ajax_referer( 'wp_editor_ajax_nonce_settings_posts', 'wp_editor_ajax_nonce_settings_posts', false ) ) {

We double checked and the protection seems to be functioning properly, so that an attacker wouldn’t be able wouldn’t be able to introduce malicious code into the inputs later in the function, so no vulnerability was there (but it didn’t hurt to escape the input).

The two other places where changes are made are identical for the purposes of the vulnerability, so we will just take a look at the changes made in /classes/WPEditorPlugins.php. In the function add_plugins_page() the GET or POST input variables “plugin” and “file” were escaped. That function is called whenever you visit the plugin’s Plugin Editor page.

When submitting malicious JavaScript in the “file” input it gets run through the function validate_file_to_edit() several lines after input is brought in to the function and since it will not be a valid file, the call to validate_file_to_edit() will die, so malicious code is never stored or echoed back out, so no cross-site scripting (XSS) occurs.

When submitting malicious JavaScript in the “plugin” input the value eventually gets out echoed out unescaped in the file /views/plugin-editor.php here:

echo __( 'Browsing <span class="current_file">', 'wp-editor' ) . $data['file'] . __( '</span> (inactive)', 'wp-editor' );

So finally we have run across an actual vulnerability that was fixed, a reflected cross-site scripting (XSS) vulnerability.

Proof of Concept

The following proof of concept will cause any available cookies to shown in alert box when logged in to WordPress. Major web browsers other than Firefox provide XSS filtering, so this proof of concept will not work in those web browsers.

Make sure to replace “[path to WordPress]” with the location of WordPress.

http://[path to WordPress]/wp-admin/plugins.php?page=wpeditor_plugin&plugin=<script>alert(document.cookie)</script>

Leave a Reply

Your email address will not be published. Required fields are marked *