The WordPress KingComposer Page Builder plugin (100,000+ active installations), fixed multiple critical vulnerabilities affecting version 2.9.2 and below that could lead to authenticated WordPress options change, content injection, stored XSS, arbitrary file deletion and remote code execution among other issues.
Broken Access Control
KingComposer is enabled by default for pages and has an option for posts as well in the ‘Generics Settings’ page:
When enabled, it leaks an important security nonce in the source of the ‘/wp-admin/index.php’ main page, accessible to any logged-in user:
The nonce is populated in the ‘kingcomposer/includes/kc.widgets.php’ script via the widgets_init
hook and is the only security check used by many of the 30+ AJAX actions found in the ‘kingcomposer/includes/kc.ajax.php’ script.
Any authenticated user, including a subscriber, can perform several critical actions.
1. WordPress Options Change
The kc_update_option
AJAX action can allow an authenticated attacker to modify any WordPress option in the options
table of the database:
public function update_option(){ check_ajax_referer( 'kc-nonce', 'security' ); $data = json_decode(base64_decode($_POST['options']), true); if( count( $data ) >0 ){ foreach( $data as $k => $v ){ echo $k; if( !empty( $k )) update_option( $k, $v ); } } ... ...
It is possible to enable registration (users_can_register
) and to set the user default role to administrator
, so that the user can register an admin account, or modify the value of siteurl
in order to redirect all traffic to an external malicious website.
2. Arbitrary files/folders deletion
The kc_installed_extensions
action AJAX is used to install extensions, but because it doesn’t properly validate paths, an attacker can recursively delete any folders and files, for instance by sending a name=../../../wp-admin/
POST request to delete the content of the ‘/wp-admin/’ folder.
3. Content Injection
The kc_push_section
action AJAX can be used by the attacker to modify the content of any page or post on the website. The new content can either replace the existing one ($_POST['overwrite']
) or be appended to it.
Several additional AJAX actions can be exploited too, for instance kc_load_section
that could let an attacker view any page or post, even if they are private or password-protected.
Stored XSS via shortcode
In ‘/kingcomposer/kingcomposer.php’, several shortcode filters are registered:
public function init(){ ... ... /* * Register shortcode filters */ $core_filters = apply_filters( 'kc-core-shortcode-filters', array( 'row', 'row_inner', 'column', 'tabs', 'tab', 'box', 'video_play', 'counter_box', 'carousel_images', 'twitter_feed', 'feature_box', 'pie_chart', 'carousel_post', 'image_gallery', 'blog_posts' ) ); foreach ($core_filters as $k => $v) { $this->add_filter ('kc_'.$v, 'kc_'.$v.'_filter'); }
Some of them do not properly escape all attributes and thus can be used to inject JavaScript. For instance, in the ‘kingcomposer/shortcodes/kc_row_inner.php’ script, the $atts
attribute isn’t always sanitized:
extract( $atts ); ... ... if( !empty( $atts['equal_height'] ) ) { $attributes[] = 'data-kc-equalheight="true"'; $attributes[] = 'data-kc-row-action="true"'; $attributes[] = 'data-kc-equalheight-align="'. $atts['column_align'] .'"'; }
An authenticated attacker can inject HTML events and JavaScript code:
[kc_row_inner id="my-id" style="1" column_align='left" onmousemove="alert(`Stored XSS via shortcode.`)' equal_height="1"] XSS test [/kc_row_inner]
Remote code execution
The ‘KingComposer > Extensions’ menu is used to manage extensions (upload, delete etc) and is only accessible to the administrator. The function handling the submitted data, process_bulk_action
, is located in the ‘kingcomposer/includes/kc.extensions.php’ script:
add_action('init', array(&$this, 'process_bulk_action')); public function process_bulk_action() { if ( isset($_POST['action']) && isset($_POST['kc-extension-action']) && isset($_POST['kc-nonce']) && wp_verify_nonce($_POST['kc-nonce'], 'kc-nonce') ){ if (!is_admin() || !current_user_can('upload_files')) { header('HTTP/1.0 403 Forbidden'); exit; }
It is loaded by the init
hook (i.e., each time WordPress loads), uses the same leaked security nonce and is only restricted to users with upload_files
capability. Users such as authors and editors also have that capability and thus can access the function. Several critical actions can be performed:
1. Remote Code Execution
The upload
action can be used to upload any PHP script because KingComposer doesn’t validate the extraction of the extension ZIP file: all files are simply extracted into the ‘/uploads/kc_extensions/’ folder. An author can add a ‘script.php’ to a ZIP file, upload it and then access it at ‘https://example.com/wp-content/uploads/kc_extensions/script.php’.
2. Arbitrary files/folders deletion
The bulk-delete
action can allow the user to recursively delete any folders and files by assigning the folder(s) relative path to the checked[]
POST array.
Recommendations
Update immediately if you have version 2.9.2 or below installed. If you are using our web application firewall for WordPress, NinjaFirewall WP Edition (free) and NinjaFirewall WP+ Edition (premium), you are protected against this vulnerability.
Timeline
Due to unsuccessful attempts to contact the author on May 25th, 2020, the issue was escalated to the wordpress.org plugins team and a new version 2.9.4 was released on June 8th, 2020.
Stay informed about the latest vulnerabilities
- Running WordPress? You can get email notifications about vulnerabilities in the plugins or themes installed on your blog.
- On Twitter: @nintechnet