High Severity Vulnerability Patched in TC Custom JavaScript

Wordfence Threat Intelligence discovered an unauthenticated stored Cross-Site Scripting(XSS) vulnerability in TC Custom JavaScript, a WordPress plugin with over 10,000 installations.

Wordfence Premium customers received a new firewall rule to provide protection against attacks targeting this vulnerability the same day. Wordfence users still using the free version received this rule after 30 days, on July 12, 2020.

We attempted to contact the plugin’s developer the same day, on June 12, 2020, but we did not receive a response. After 10 days without an initial response, we contacted the WordPress Plugins team on June 22, 2020. An initial patch was released the next day, on June 23, 2020, and a full patch was released on June 29, 2020.

Description: Unauthenticated Stored Cross-Site Scripting(XSS)
Affected Plugin: TC Custom JavaScript
Plugin Slug: tc-custom-javascript
Affected Versions: < 1.2.2
CVE ID: CVE-2020-14063
CVSS Score: 8.3(high)
Fully Patched Version: 1.2.2

TC Custom JavaScript is a WordPress plugin that allows site owners to add custom JavaScript to every page on a site and emphasizes a minimalist approach. While this kind of functionality can be incredibly useful, it can also be incredibly dangerous without proper access controls.

This plugin ran the TCCJ_Core_Content::update function immediately upon startup. This was unusual, as most WordPress plugins register functions to be run at predictable points in the WordPress load process.

As a result, the update function ran before WordPress access control functions, such as capability checks and nonce verification, could be used. This, combined with the lack of capability checks and nonce verification on the function, made it possible for unauthorized visitors to use the update function.

The update function used a companion function, has_update_request, to check if the tccj-update POST parameter was supplied and set to Update. If this check passed, then the update function would accept the contents of the tccj-content POST parameter and add it to the database.

class TCCJ_Core_Content {
    public static function update() {
        if ( self::has_update_request() ) {
            if ( get_magic_quotes_gpc() )
                $tccj_content = stripslashes( $_POST['tccj-content'] );
                $tccj_content = $_POST['tccj-content'];
            // Sanitizing data before insert to database
            $tccj_content = wp_check_invalid_utf8( $tccj_content, true );
            $tccj_content = htmlentities( $tccj_content );
            if ( ! get_magic_quotes_runtime() )
                $tccj_content = addslashes( $tccj_content );
            update_option( 'tccj_content', $tccj_content );
    private static function has_update_request() {
        if ( isset( $_POST['tccj-update'] ) && ( $_POST['tccj-update'] == 'Update' ) )
            return true;
            return false;

While the update function did run htmlentities on the content provided by tccj-content before storing it, this didn’t provide any additional safety, as the TCCJ_Core_Frontend::print_script_in_footer function used to display the added script not only used html_entity_decode on the stored content but also added <script> tags around it.

class TCCJ_Core_Frontend {
    public static function print_script_in_footer() {
        //$tccj_content = sanitize_text_field( get_option( 'tccj_content', '' ) );
        $tccj_content = get_option( 'tccj_content', '' );
        $tccj_content = stripslashes( $tccj_content );
        $tccj_content = html_entity_decode( $tccj_content );
        if ( $tccj_content != '' ) {
            echo '<script type="text/javascript">' . $tccj_content . '</script>';

As such, an attacker could send a POST request to any location on a vulnerable site with the tccj-update parameter set to Update and the tccj-content parameter set to malicious JavaScript, and this JavaScript would display in the footer of every page on the site.

Malicious JavaScript of this type can be used to redirect visitors to malvertising sites or steal payment information. Even worse, it can detect when an administrator visits the site and send a request on their behalf to infect files with a backdoor or possibly create a new, malicious administrator user account leading to takeover of the entire site.

Soure Credit – High Severity Vulnerability Patched in TC Custom JavaScript

Wordpress Experts
Elevating Your WordPress Experience Beyond Limits.