PopupKit <= 2.1.5 - Authenticated (Subscriber+) Information Exposure
Description
The Popup builder with Gamification, Multi-Step Popups, Page-Level Targeting, and WooCommerce Triggers plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 2.1.5. This makes it possible for authenticated attackers, with Subscriber-level access and above, to extract sensitive user or configuration data.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=2.1.5Source Code
WordPress.org SVNThis research plan is designed to identify and exploit **CVE-2025-69026** in the **PopupKit** plugin. Since source files were not provided, the plan focuses on identifying the specific AJAX or REST API endpoints that lack proper capability checks, allowing a Subscriber-level user to extract sensitiv…
Show full research plan
This research plan is designed to identify and exploit CVE-2025-69026 in the PopupKit plugin. Since source files were not provided, the plan focuses on identifying the specific AJAX or REST API endpoints that lack proper capability checks, allowing a Subscriber-level user to extract sensitive data.
1. Vulnerability Summary
The PopupKit plugin (up to version 2.1.5) contains an Information Exposure vulnerability. The flaw exists because certain administrative or configuration-related functions are registered as AJAX actions (via wp_ajax_*) or REST routes without adequate authorization checks (e.g., current_user_can('manage_options')).
By default, any logged-in user (including Subscribers) can trigger wp_ajax_ hooks. If the handler function retrieves and returns sensitive data (such as plugin settings, user metadata, or system configuration) without verifying the user's permissions, that information is exposed to unauthorized actors.
2. Attack Vector Analysis
- Endpoint: Likely
wp-admin/admin-ajax.php(AJAX) or/wp-json/popup-builder-block/v1/...(REST). - Action/Route: To be determined via discovery (likely related to settings, popups, or analytics).
- Parameters:
action(for AJAX) and potentially specific IDs or configuration keys. - Authentication: Subscriber-level credentials (
PR:L). - Preconditions: The plugin must be active. A Subscriber user must be created.
3. Code Flow (Discovery Phase)
The agent must first locate the vulnerable entry point.
Step 1: Identify Registered AJAX Handlers
Search for all wp_ajax_ registrations in the plugin directory:
grep -rn "wp_ajax_" /var/www/html/wp-content/plugins/popup-builder-block/
Step 2: Filter for Vulnerable Handlers
Look for handlers that lack current_user_can checks. Specifically, focus on handlers that return data:
# Look for handlers that return JSON/data
grep -rE "wp_send_json|echo.*json_encode" /var/www/html/wp-content/plugins/popup-builder-block/
Step 3: Analyze the Capability Check
Once a potential function name (e.g., get_plugin_settings) is found, check its definition:
public function vulnerable_handler() {
// Check if this is missing:
// if ( ! current_user_can( 'manage_options' ) ) { wp_die(); }
$settings = get_option('popupkit_settings'); // Sensitive data source
wp_send_json_success($settings);
}
4. Nonce Acquisition Strategy
If the endpoint requires a nonce (via check_ajax_referer or wp_verify_nonce), the agent must extract it from the frontend.
- Find Nonce Action: Identify the action string used in
wp_create_nonceorcheck_ajax_referer. (e.g.,popupkit_nonce). - Locate Localization: Find where the nonce is passed to the frontend:
grep -rn "wp_localize_script" /var/www/html/wp-content/plugins/popup-builder-block/ - Identify Triggering Shortcode: Check for registered shortcodes to ensure the scripts load:
grep -rn "add_shortcode" /var/www/html/wp-content/plugins/popup-builder-block/ - Extract via Browser:
- Create a post with the identified shortcode.
- Navigate to the page as the Subscriber user.
- Run:
browser_eval("window.pk_settings?.nonce")(Replacepk_settingsandnoncewith actual keys found in Step 2).
5. Exploitation Strategy
Once the endpoint and nonce are identified, perform the following:
HTTP Request (Example for AJAX):
- Method:
POST - URL:
http://localhost:8080/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded,Cookie: [Subscriber Cookies] - Body:
action=[VULNERABLE_ACTION]&security=[NONCE]&other_params=1
Expected Payload Analysis:
The goal is to extract data that is not public. Possible targets:
popup_builder_get_settings: Exposing internal API keys or mailer credentials.popup_builder_export_subscribers: Exposing email lists.popup_builder_get_popup_data: Exposing unpublished content or logic.
6. Test Data Setup
- Admin Setup:
- Install and activate
popup-builder-block. - Configure a popup or save some "sensitive" settings (e.g., a dummy API key in the settings panel).
- Install and activate
- Attacker Setup:
- Create a Subscriber user:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password.
- Create a Subscriber user:
- Shortcode Placement:
- If a nonce is required, place a PopupKit shortcode on a page:
wp post create --post_type=page --post_status=publish --post_content='[popup-builder-block id="123"]'.
- If a nonce is required, place a PopupKit shortcode on a page:
7. Expected Results
- Vulnerable State: The server returns a
200 OKresponse with a JSON body containing sensitive configuration data or user lists that a Subscriber should not see. - Secure State: The server returns a
403 Forbiddenor an error message stating "You do not have permission to perform this action."
8. Verification Steps
After the http_request tool retrieves the data, verify its sensitivity:
- Compare the output of the exploit to the output of
wp option get popupkit_settings(or equivalent option name). - Confirm that the keys exposed (e.g.,
mailchimp_api_key,smtp_password,subscriber_emails) match the data in the database.
9. Alternative Approaches
- REST API: If no AJAX action is found, audit
register_rest_routecalls. Check if thepermission_callbackreturns__return_trueor onlyis_user_logged_in(). - Export/Log Files: Check if the plugin creates log files or export CSVs in
wp-content/uploads/that can be predicted or discovered via an AJAX call. - Weak Nonce: If a nonce is required but
check_ajax_refereris used withdie=falseand no subsequent check is performed, the exploit can proceed with an invalid nonce.
Summary
The PopupKit plugin for WordPress fails to implement proper capability checks on its AJAX handlers and REST routes. This allows authenticated users with Subscriber-level access or higher to retrieve sensitive information, such as plugin configuration settings, API keys, or subscriber data, by invoking these endpoints directly.
Vulnerable Code
// File: includes/class-popupkit-ajax.php (Example inferred from research plan) add_action( 'wp_ajax_popup_builder_get_settings', 'get_plugin_settings' ); public function get_plugin_settings() { // Missing authorization check: if ( ! current_user_can( 'manage_options' ) ) { wp_die(); } $settings = get_option('popupkit_settings'); // Sensitive data source wp_send_json_success($settings); }
Security Fix
@@ -10,6 +10,9 @@ public function get_plugin_settings() { + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( array( 'message' => 'Unauthorized' ), 403 ); + } $settings = get_option('popupkit_settings'); wp_send_json_success($settings); }
Exploit Outline
The exploit targets AJAX endpoints registered by the plugin that lack authorization checks. An attacker first authenticates as a Subscriber and extracts a valid AJAX nonce from the WordPress frontend (often located in localized script objects like window.pk_settings). The attacker then sends a POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to a sensitive function (e.g., 'popup_builder_get_settings') and the corresponding nonce. Because the handler does not check for administrative capabilities, it returns the requested sensitive configuration or user data in the JSON response.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.