CVE-2026-5293

診断ジェネレータ作成プラグイン <= 1.4.16 - Authenticated (Subscriber+) Stored Cross-Site Scripting via 'js' Parameter

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The 診断ジェネレータ作成プラグイン (Diagnosis Generator) plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'js' parameter in versions up to and including 1.4.16. This is due to missing authorization checks and insufficient input sanitization in the themeFunc() function. The function is hooked to 'admin_init' and processes theme update requests without verifying user capabilities, allowing any authenticated user (including subscribers) to save malicious JavaScript to theme files. Additionally, the save() function uses stripslashes() which removes WordPress's magic quotes protection. This makes it possible for authenticated attackers, with subscriber-level access and above, to inject arbitrary web scripts in theme files that will execute whenever a user accesses a page containing the diagnosis form shortcode.

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<=1.4.16
PublishedMay 19, 2026
Last updatedMay 20, 2026
Affected pluginos-diagnosis-generator
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-5293 ## 1. Vulnerability Summary **CVE-2026-5293** is a Stored Cross-Site Scripting (XSS) vulnerability in the **診断ジェネレータ作成プラグイン (Diagnosis Generator)** plugin (versions <= 1.4.16). The vulnerability exists because the `themeFunc()` function, which is hooked t…

Show full research plan

Exploitation Research Plan: CVE-2026-5293

1. Vulnerability Summary

CVE-2026-5293 is a Stored Cross-Site Scripting (XSS) vulnerability in the 診断ジェネレータ作成プラグイン (Diagnosis Generator) plugin (versions <= 1.4.16). The vulnerability exists because the themeFunc() function, which is hooked to admin_init, fails to perform authorization checks (e.g., current_user_can()) or nonce verification.

An authenticated user with Subscriber-level permissions or higher can send a request containing a malicious js parameter. The plugin processes this request and saves the input into theme-related configuration files using the save() function. Because the save() function employs stripslashes(), it bypasses WordPress's automatic magic quotes, allowing the injection of arbitrary JavaScript. This payload is subsequently executed in the context of any user (including administrators) who visits a page containing the diagnosis form shortcode.

2. Attack Vector Analysis

  • Vulnerable Endpoint: Any WordPress admin path (typically /wp-admin/admin-ajax.php or /wp-admin/admin-post.php) triggers the admin_init hook.
  • Vulnerable Function: themeFunc() (inferred to be inside the main plugin file or a theme-handling class).
  • Trigger Parameter: A POST request containing a specific action or identifier to enter the themeFunc() logic, plus the js parameter.
  • Payload Parameter: js
  • Authentication: Authenticated (Subscriber or higher).
  • Preconditions: The plugin must be active. To trigger the XSS on the frontend, a page must contain the plugin's shortcode (typically [os-diagnosis-generator]).

3. Code Flow

  1. Entry Point: An authenticated user sends a POST request to /wp-admin/admin-ajax.php.
  2. Hook Execution: WordPress triggers the admin_init hook.
  3. Vulnerable Function: The plugin's registered callback themeFunc() executes.
  4. Lack of Authorization: themeFunc() fails to check for current_user_can( 'manage_options' ).
  5. Data Processing: The code checks for the presence of a 'theme update' trigger (e.g., a specific $_POST key).
  6. Sanitization Bypass: The js parameter is passed to a save() function. This function uses stripslashes($_POST['js']), removing any escaping applied by WordPress core.
  7. Persistence (Sink): The content of the js parameter is written to a file (e.g., a template file in wp-content/uploads/os-diagnosis-generator/ or similar) or stored in the database and then written to a script file.
  8. Execution: When the diagnosis form is rendered via shortcode, the stored JavaScript is included in the page output.

4. Nonce Acquisition Strategy

The vulnerability description explicitly mentions "missing authorization checks," which strongly suggests that the admin_init hook lacks both capability checks and nonce verification (check_admin_referer or check_ajax_referer).

If a nonce is required for the "theme update" request, it is likely localized for the plugin's admin interface.

  1. Identify Script Handles: Look for wp_localize_script calls in the plugin source (e.g., searching for os-diagnosis-generator-admin).
  2. Creation of Admin Page: Since the attacker is a Subscriber, they cannot normally see the plugin's settings page. However, because the hook is on admin_init, the logic runs on any admin page they can access (like profile.php).
  3. Bypass Check: If the plugin code uses check_admin_referer( 'some_action', 'some_nonce', false ) without checking the return value, the nonce is bypassed.

Assumed Strategy: Attempt the exploit without a nonce first. If it fails, search the plugin source for wp_create_nonce.

5. Exploitation Strategy

The goal is to inject a script that will execute when the diagnosis generator is loaded.

Step 1: Authentication

Log in as a Subscriber user.

  • URL: /wp-login.php
  • Tool: http_request

Step 2: Identify Injection Trigger

The themeFunc() function likely looks for a specific POST parameter to initiate the save process. Based on the plugin name and description, we will look for keys like os_diagnosis_save, theme_update, or update_js.
(Inferred request parameters based on typical plugin patterns):

  • Action: os_diagnosis_generator_update_theme (inferred)
  • Parameter: js

Step 3: Send Malicious Request

Send a POST request to /wp-admin/admin-ajax.php (or similar) to save the malicious JS.

  • Request Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body: action=themeFunc&js=</script><script>alert(document.domain)</script>&(trigger_param)=1
    (Note: The exact 'action' and 'trigger_param' need to be verified by grepping the plugin source for add_action('admin_init', ...))

Step 4: Trigger the XSS

Visit a page containing the plugin's shortcode.

  • URL: http://localhost:8080/diagnosis-page/

6. Test Data Setup

  1. Plugin Installation: Install and activate os-diagnosis-generator <= 1.4.16.
  2. User Creation: Create a Subscriber user.
    • wp user create attacker attacker@example.com --role=subscriber --user_pass=password
  3. Shortcode Page: Create a public page with the diagnosis shortcode.
    • wp post create --post_type=page --post_title="Diagnosis" --post_status=publish --post_content="[os-diagnosis-generator]"
    • (Note: Verify the exact shortcode slug by running grep -r "add_shortcode" wp-content/plugins/os-diagnosis-generator)

7. Expected Results

  • The POST request from the Subscriber user returns a success code (e.g., 200 OK or a redirect).
  • When navigating to the page created in Step 6, a JavaScript alert box displaying the document domain appears.
  • Inspecting the page source reveals the injected <script>alert(document.domain)</script> payload.

8. Verification Steps

  1. Check Filesystem: Use WP-CLI to check if a new JS file was created or modified in the plugin's directory or uploads.
    • ls -R wp-content/uploads/os-diagnosis-generator/
  2. Check Options: Check if the JS is stored in the WordPress options table.
    • wp option get os_diagnosis_generator_custom_js (inferred option name)
  3. Verify Frontend Render: Use http_request to fetch the diagnosis page and grep for the payload.
    • http_request(url='http://localhost:8080/diagnosis-page/') -> search for alert(document.domain) in the response body.

9. Alternative Approaches

  • Parameter Polling: If the specific trigger parameter for themeFunc is unknown, grep the plugin source for $_POST inside the function hooked to admin_init.
  • CSRF: If the plugin checks for authentication but lacks nonces, an administrator could be tricked into clicking a link that injects the JS payload.
  • Shortcode Attribute XSS: If the js parameter injection fails, investigate if the shortcode handler itself reflects attributes without escaping.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Diagnosis Generator plugin for WordPress (up to version 1.4.16) is vulnerable to Stored Cross-Site Scripting (XSS) via the 'js' parameter. This is caused by the themeFunc() function being improperly hooked to admin_init without capability checks or nonces, combined with the use of stripslashes() which bypasses WordPress's default magic quotes protection.

Vulnerable Code

/* In the main plugin file or theme-handling file */
add_action('admin_init', 'themeFunc');

function themeFunc() {
    // Vulnerability: No current_user_can() check or nonce verification
    // Any authenticated user reaching admin_init (including subscribers) can trigger this
    if (isset($_POST['js'])) {
        // Vulnerability: stripslashes() removes escape characters, allowing raw script tags
        $js_content = stripslashes($_POST['js']);
        $this->save($js_content);
    }
}

Security Fix

--- a/os-diagnosis-generator.php
+++ b/os-diagnosis-generator.php
@@ -10,6 +10,13 @@
 function themeFunc() {
+    if ( ! current_user_can( 'manage_options' ) ) {
+        return;
+    }
+    if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'save_theme_js' ) ) {
+        return;
+    }
+
     if ( isset( $_POST['js'] ) ) {
-        $js = stripslashes( $_POST['js'] );
+        $js = sanitize_textarea_field( stripslashes( $_POST['js'] ) );
         $this->save( $js );
     }
 }

Exploit Outline

The attacker first authenticates as a low-privileged user (Subscriber or higher). They then construct a POST request to any endpoint that triggers the 'admin_init' hook (such as /wp-admin/admin-ajax.php). The payload includes the specific trigger parameter for the themeFunc() logic and the 'js' parameter containing a malicious script (e.g., <script>alert(document.domain)</script>). Because the function lacks authorization checks and uses stripslashes(), the payload is saved to the plugin's theme configuration. Finally, the attacker visits a page containing the plugin's shortcode to execute the stored script in the context of other users' browsers.

Check if your site is affected.

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