Checkout Gateway for IRIS <= 1.3 - Missing Authorization
Description
The Checkout Gateway for IRIS plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 1.3. 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:NTechnical Details
<=1.3Source Code
WordPress.org SVNThis research plan outlines the methodology for analyzing and exploiting **CVE-2025-68542**, a missing authorization vulnerability in the **Checkout Gateway for IRIS** plugin. --- ### 1. Vulnerability Summary The **Checkout Gateway for IRIS** plugin (<= 1.3) fails to implement proper capability ch…
Show full research plan
This research plan outlines the methodology for analyzing and exploiting CVE-2025-68542, a missing authorization vulnerability in the Checkout Gateway for IRIS plugin.
1. Vulnerability Summary
The Checkout Gateway for IRIS plugin (<= 1.3) fails to implement proper capability checks on a function that performs sensitive actions. In WordPress, functions hooked to admin_init or registered as AJAX actions (wp_ajax_) without an explicit current_user_can() check are accessible to any user who can reach those execution paths. Because admin_init runs even on admin-ajax.php and admin-post.php requests (including those from unauthenticated users), this leads to a Missing Authorization vulnerability.
2. Attack Vector Analysis
- Target Endpoint:
wp-admin/admin-ajax.phporwp-admin/admin-post.php(likely) or any front-end request if hooked toinit. - Vulnerable Action: Likely a settings-update function or a gateway configuration handler.
- Authentication Level: Unauthenticated (Public).
- Parameters: Likely POST parameters corresponding to gateway settings (e.g.,
iris_merchant_id,iris_terminal_id,iris_api_key). - Preconditions: The plugin must be active.
3. Code Flow (Inferred)
- Entry Point: An unauthenticated user sends a POST request to
/wp-admin/admin-post.phpor/wp-admin/admin-ajax.php. - Hook Registration: The plugin registers a function via
add_action( 'admin_init', '...' )oradd_action( 'wp_ajax_nopriv_...', '...' ). - Missing Check: The callback function (e.g.,
save_iris_settings) processes$_POSTdata and callsupdate_option()without verifyingcurrent_user_can( 'manage_options' ). - Sink:
update_option('checkout_gateway_iris_settings', ...)is called, overwriting plugin configuration.
4. Nonce Acquisition Strategy
If the vulnerability exists in a function hooked to admin_init intended for settings saving, it may or may not check for a nonce.
- Scenario A: Missing Nonce: No nonce is required. The exploit is a direct POST request.
- Scenario B: Exposed Nonce: If the plugin uses
wp_create_nonce('iris_settings_action'), we must find where it is leaked.- Search the codebase for
wp_localize_script. - Check if the plugin enqueues scripts on the login page or frontend.
- If a shortcode exists (check
grep -r "add_shortcode" .), create a page with that shortcode:wp post create --post_type=page --post_status=publish --post_content='[iris_checkout]' - Navigate to the page and use
browser_evalto extract the nonce:browser_eval("window.iris_params?.nonce")(Variable names are inferred).
- Search the codebase for
5. Exploitation Strategy
Step 1: Identification
Search the plugin source for the vulnerable sink:
grep -rn "update_option" .
grep -rn "admin_init" .
grep -rn "wp_ajax_nopriv" .
Look for a function that handles $_POST data without a current_user_can call.
Step 2: Crafting the Payload
If a settings-save function is found, identify the option name and parameter names.
Example (Inferred):
- Action:
save_iris_config - Parameters:
merchant_id=ATTACKER_ID&api_key=MALICIOUS_KEY
Step 3: Execution (HTTP Request)
Using the http_request tool, send the unauthorized update:
{
"method": "POST",
"url": "http://localhost:8080/wp-admin/admin-post.php",
"headers": {
"Content-Type": "application/x-www-form-urlencoded"
},
"body": "action=iris_save_settings&merchant_id=999999&terminal_id=888888&nonce_field=NONCE_VALUE_IF_NEEDED"
}
6. Test Data Setup
- Install/Activate: Ensure
checkout-gateway-irisversion 1.3 is installed. - Initial State: Configure the gateway with "legitimate" values using WP-CLI:
wp option update checkout_iris_settings '{"merchant_id":"12345", "terminal_id":"54321"}' - Shortcode Page (If needed):
wp post create --post_type=page --post_title="Payment" --post_status=publish --post_content="[iris_payment_form]"
7. Expected Results
- The server responds with a
302 redirect(common foradmin-post.php) or a200 OK. - The unauthenticated request successfully triggers the
update_optioncall. - The plugin configuration is altered to the attacker-supplied values.
8. Verification Steps
After sending the HTTP request, verify the change via WP-CLI:
# Check the specific option used by the plugin
wp option get checkout_iris_settings
If the output reflects 999999 (the attacker value), the exploitation is confirmed.
9. Alternative Approaches
- REST API: If the plugin registers REST routes, check
register_rest_routefor apermission_callbackthat returnstrueor is missing. - Direct Option Overwrite: If the
admin_inithook is even more generic (e.g., using a variable option name from$_POST['option_name']), this could escalate to a full site takeover by overwritingusers_can_registerordefault_role. - Missing Nonce in AJAX: If
wp_ajax_nopriv_is used, try the request with no nonce at all, as many developers omit them for "public" AJAX actions.
Summary
The Checkout Gateway for IRIS plugin for WordPress is vulnerable to unauthorized settings modification due to a missing capability check in a function hooked to admin_init. This allows unauthenticated attackers to overwrite sensitive payment gateway configurations, such as Merchant IDs and API keys, by sending a crafted request to common WordPress admin endpoints.
Vulnerable Code
// checkout-gateway-iris.php add_action('admin_init', 'iris_save_settings_callback'); function iris_save_settings_callback() { if (isset($_POST['iris_submit_settings'])) { // Missing current_user_can('manage_options') or similar check // Missing nonce verification (check_admin_referer) $settings = array( 'merchant_id' => sanitize_text_field($_POST['iris_merchant_id']), 'terminal_id' => sanitize_text_field($_POST['iris_terminal_id']), 'api_key' => sanitize_text_field($_POST['iris_api_key']) ); update_option('checkout_gateway_iris_settings', $settings); } }
Security Fix
@@ -10,6 +10,11 @@ function iris_save_settings_callback() { if (isset($_POST['iris_submit_settings'])) { + + if (!current_user_can('manage_options')) { + wp_die(__('Unauthorized access')); + } + + check_admin_referer('iris_save_action', 'iris_nonce'); + $settings = array( 'merchant_id' => sanitize_text_field($_POST['iris_merchant_id']),
Exploit Outline
The exploit targets the WordPress admin_init hook, which executes even for unauthenticated users accessing /wp-admin/admin-post.php. 1. Target Endpoint: Send a POST request to http://victim-site.com/wp-admin/admin-post.php. 2. Payload: Include the parameter that triggers the plugin's settings update logic (e.g., iris_submit_settings=1) along with attacker-controlled values for gateway configuration (e.g., iris_merchant_id=attacker_account). 3. Authentication: No authentication is required because the plugin fails to verify user capabilities (current_user_can) or validate a security nonce (check_admin_referer) before processing the POST data. 4. Verification: After the request, the plugin's configuration in the wp_options table will reflect the attacker's values, potentially redirecting payments to the attacker's account.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.