On June 15 2020, one of our partners became aware of a security issue with KingComposer.  If you’ve never heard of it, it is a WordPress plugin installed on over 100,000 sites.

During the investigation of these vulnerabilities, our partner discovered an unpatched reflected Cross-Site Scripting (XSS) vulnerability.  This led to them working closely with the WordPress plugins team as well as the developer to apply an update to the plugin.


What is KingComposer?

KingComposer is a WordPress plugin that allows Drag and Drop page building, and it registers a number of AJAX actions to accomplish this.  One of these AJAX actions was no longer actively used by the plugin, but could still be used by sending a POST request to wp-admin/admin-ajax.php with the action parameter set to kc_install_online_preset.


What is Reflected Cross-Site Scripting (XSS)?

Reflected Cross-Site Scripting (or XSS) arises when an application receives data in an HTTP request and includes that data within the immediate response in an unsafe way.  Suppose a website has a search function which receives the user-supplied search term in a URL parameter:


The application echoes the supplied search term in the response to this URL:

<p>You searched for: gift</p>

Assuming the application doesn’t perform any other processing of the data, an attacker can construct an attack like this:


This URL results in the following response:

<p>You searched for: <script>/* Bad stuff here... */</script></p>

If another user of the application requests the attacker’s URL, then the script supplied by the attacker will execute in the victim user’s browser, in the context of their session with the application.


What’s the risk?

Reflected XSS vulnerabilities have characteristics of this and Cross-Site Request Forgery (CSRF) vulnerabilities.  Much like a CSRF attack, exploiting a Reflected XSS vulnerability usually relies on an attacker tricking their victim into clicking a malicious link which sends the victim to the vulnerable site along with a malicious payload.  This can be done in a number of ways, but it is common to first link to an intermediate site controlled by the attacker, which then sends a request containing a malicious payload to the vulnerable site on behalf of the victim.

A notable distinction between the stored XSS vulnerabilities more commonly found and reflected XSS vulnerabilities such as this, is that the malicious scripts that are used as part of the exploit are not actually stored anywhere in the database with reflected XSS vulnerabilities.  Rather, the malicious scripts are reflected and executed once during the exploit.

As with Stored XSS attacks, the malicious payload will be executed in the victim’s browser.  However, with reflected XSS, the vulnerable site would immediately output (reflect) the malicious JavaScript payload, which would be executed a single time in the victim’s browser instead of being stored in the database for later execution.

This could be used in a variety of attacks.  For instance, if the victim was a logged-in administrator on the vulnerable site, the reflected JavaScript could be used to create a new, malicious administrator account controlled by the attacker.

In order for reflected XSS attacks to successfully exploit a user, an attacker needs to trick the user into performing an action.  For that reason, we highly recommend remaining vigilant when clicking on links or attachments in comments, emails, and other communication sources unless you are sure of their integrity and legitimacy.


What is the vulnerable function of KingComposer?

For those of you who want a code snippet, here it is:

public function install_online_preset(){
    $data = isset($_POST['kc-online-preset-data']) ? esc_attr($_POST['kc-online-preset-data']) : '';
    $link = isset($_POST['kc-online-preset-link']) ? esc_url($_POST['kc-online-preset-link']) : '';
    $link = str_replace( 'http://features.kingcomposer.com/', 'https://kingcomposer.com/presets/', $link);
    $callback = '
    <script type="text/javascript">
        top.kc.cfg.preset_link = "'.$link.'";
        top.kc.backbone.push(\''.str_replace( "\n", '\'+"\n"+\'', base64_decode($data)).'\');
    echo $callback;


How can I stay safe?

As a rule of thumb always keep your plugins up-to-date.  If you’re not sure how to do this, or if you aren’t actively monitoring your site – talk to us today.  If you’re hosted with us – we’ve already made the changes you need to be safe.  It might be another good reason to think about moving your site to us…