[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$ffHOmfiP0HNcUmRAWQgdqLhy4aH5sSDO2rx8hlt76CsU":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":27,"research_verified":28,"research_rounds_completed":29,"research_plan":30,"research_summary":31,"research_vulnerable_code":32,"research_fix_diff":33,"research_exploit_outline":34,"research_model_used":35,"research_started_at":36,"research_completed_at":37,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":28,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":28,"source_links":38},"CVE-2026-24362","ultimate-post-kit-addons-for-elementor-missing-authorization","Ultimate Post Kit Addons for Elementor \u003C= 4.0.21 - Missing Authorization","The Ultimate Post Kit Addons for Elementor plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 4.0.21. This makes it possible for authenticated attackers, with Subscriber-level access and above, to perform an unauthorized action.","ultimate-post-kit",null,"\u003C=4.0.21","4.0.22","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-03-18 00:00:00","2026-03-27 19:46:41",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F50b19d49-15d6-4285-af3b-00ff96bcb349?source=api-prod",10,[22,23,24,25,26],"admin\u002Fadmin-biggopti.php","admin\u002Fassets\u002Fjs\u002Fupk-biggopti.min.js","includes\u002Fsetup-wizard\u002Finit.php","readme.txt","ultimate-post-kit.php","researched",false,3,"# Research Plan: CVE-2026-24362 - Missing Authorization in Ultimate Post Kit\n\n## 1. Vulnerability Summary\nThe **Ultimate Post Kit Addons for Elementor** plugin (up to 4.0.21) contains a missing authorization vulnerability in its `Biggopties` class. Specifically, the AJAX handlers registered for dismissing notices and fetching remote API data lack capability checks (e.g., `current_user_can( 'manage_options' )`). This allows authenticated users with Subscriber-level permissions to trigger administrative actions, such as forcing the site to fetch promotional data from a remote API and updating internal transients.\n\n## 2. Attack Vector Analysis\n- **Target Endpoint**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **AJAX Actions**: \n    - `upk_fetch_api_biggopties` (Triggers remote API fetch and transient update)\n    - `ultimate-post-kit-biggopties` (Dismisses notices\u002Fupdates notice state)\n- **Parameters**: \n    - `action`: `upk_fetch_api_biggopties` or `ultimate-post-kit-biggopties`\n    - `_wpnonce`: A nonce associated with the `UltimatePostKitBiggoptiConfig` JavaScript object.\n    - (For dismiss action): `id`, `meta`, `time`.\n- **Preconditions**: \n    - User must be authenticated (Subscriber or higher).\n    - The plugin `ultimate-post-kit` must be active.\n\n## 3. Code Flow\n1. **Entry Point**: The `UltimatePostKit\\Biggopties` class registers AJAX hooks in its `__construct` method (found in `admin\u002Fadmin-biggopti.php`):\n   ```php\n   add_action('wp_ajax_ultimate-post-kit-biggopties', [$this, 'dismiss']);\n   add_action('wp_ajax_upk_fetch_api_biggopties', [$this, 'ajax_fetch_api_biggopties']);\n   ```\n2. **AJAX Handler**: When a Subscriber sends a request with `action=upk_fetch_api_biggopties`, the `ajax_fetch_api_biggopties` method is executed.\n3. **Logic**: The handler likely calls `get_api_biggopties_data()`, which:\n   - Performs an outbound HTTP request to `https:\u002F\u002Fapi.sigmative.io\u002Fprod\u002Fstore\u002Fapi\u002Fbiggopti\u002Fapi-data-records`.\n   - Saves the result to a transient named `bdt_api_biggopties` using `set_transient()`.\n4. **Vulnerability**: Neither `dismiss` nor `ajax_fetch_api_biggopties` contains a check for administrative capabilities. While they check nonces, these nonces are exposed to all logged-in users who can access the admin dashboard (including Subscribers visiting `\u002Fwp-admin\u002Fprofile.php`).\n\n## 4. Nonce Acquisition Strategy\nThe nonce is localized for the script `upk-biggopti` (JS file: `admin\u002Fassets\u002Fjs\u002Fupk-biggopti.min.js`).\n\n1. **Login**: Authenticate as a Subscriber.\n2. **Navigate**: Access the WordPress dashboard at `\u002Fwp-admin\u002Fprofile.php`.\n3. **Extract Nonce**: The nonce is stored in the global JavaScript variable `UltimatePostKitBiggoptiConfig`.\n4. **JS Variable**: `window.UltimatePostKitBiggoptiConfig.nonce`\n5. **Procedure**:\n   - Use `browser_navigate` to go to `\u002Fwp-admin\u002Fprofile.php`.\n   - Use `browser_eval` to run: `return window.UltimatePostKitBiggoptiConfig ? window.UltimatePostKitBiggoptiConfig.nonce : null;`.\n\n## 5. Exploitation Strategy\n\n### Phase 1: Force API Data Fetch\n1.  **Request**: POST to `\u002Fwp-admin\u002Fadmin-ajax.php`.\n2.  **Payload**:\n    ```http\n    action=upk_fetch_api_biggopties&_wpnonce=[EXTRACTED_NONCE]\n    ```\n3.  **Expected Outcome**: The server returns a JSON response (likely `success: true` or a data object) and performs an outbound request to the Sigmative API, overwriting the `bdt_api_biggopties` transient.\n\n### Phase 2: Dismiss Admin Notice (Alternative)\n1.  **Request**: POST to `\u002Fwp-admin\u002Fadmin-ajax.php`.\n2.  **Payload**:\n    ```http\n    action=ultimate-post-kit-biggopties&id=test-id&meta=test-meta&time=3600&_wpnonce=[EXTRACTED_NONCE]\n    ```\n3.  **Expected Outcome**: Modification of notice state (likely stored in options or user meta), demonstrating unauthorized state change.\n\n## 6. Test Data Setup\n1.  **Users**: Create a user with the `subscriber` role.\n2.  **Plugin State**: Ensure \"Ultimate Post Kit\" is active.\n3.  **Cleanup**: Delete the transient `bdt_api_biggopties` before testing to ensure the exploit actually recreates it:\n    - `wp transient delete bdt_api_biggopties`\n\n## 7. Expected Results\n- A successful response from the AJAX endpoint (HTTP 200).\n- The `bdt_api_biggopties` transient should exist\u002Fbe updated in the database.\n- The logs (if monitored) should show a `wp_remote_get` request to `https:\u002F\u002Fapi.sigmative.io\u002F...`.\n\n## 8. Verification Steps\nAfter performing the HTTP request as a Subscriber, verify the impact using WP-CLI:\n1.  **Check Transient**:\n    ```bash\n    wp transient get bdt_api_biggopties\n    ```\n    If the transient contains data, the unauthorized action was successful.\n2.  **Verify Nonce Usage**: Confirm the response body from the `http_request` matches the expected format from `ajax_fetch_api_biggopties`.\n\n## 9. Alternative Approaches\nIf `upk_fetch_api_biggopties` is patched or restricted, target the `Setup_Wizard`'s manual request:\n- **Unauthorized UI Access**: Navigate to `\u002Fwp-admin\u002Findex.php?upk_setup_wizard=show` as a Subscriber.\n- **Verification**: Use `browser_eval` to check if the class `.bdt-setup-wizard-active` is added to the `body` tag, indicating the wizard UI was successfully loaded for a low-privileged user.","The Ultimate Post Kit Addons for Elementor plugin is vulnerable to unauthorized access due to missing capability checks in several AJAX handlers, specifically those related to administrative notice management (Biggopties) and the Setup Wizard. This allows authenticated users with Subscriber-level permissions to perform administrative actions such as dismissing site-wide notices, forcing remote API data fetches that update transients, and importing Elementor templates from arbitrary URLs.","\u002F\u002F admin\u002Fadmin-biggopti.php - AJAX handlers for notices and API fetching\npublic function __construct() {\n    add_action('wp_ajax_ultimate-post-kit-biggopties', [$this, 'dismiss']);\n    add_action('wp_ajax_upk_fetch_api_biggopties', [$this, 'ajax_fetch_api_biggopties']);\n}\n\npublic function ajax_fetch_api_biggopties() {\n    if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'ultimate-post-kit-biggopties' ) ) {\n        wp_send_json_error([ 'message' => 'forbidden' ]);\n    }\n    \u002F\u002F No current_user_can() check before fetching and set_transient()\n    $biggopties = $this->get_api_biggopties_data();\n    \u002F\u002F ... (truncated)\n}\n\n---\n\n\u002F\u002F includes\u002Fsetup-wizard\u002Finit.php - Template import handlers in 4.0.21\nadd_action('wp_ajax_import_elementor_template', function () {\n    check_ajax_referer( 'setup_wizard_nonce', 'nonce' );\n\n    \u002F\u002F Missing current_user_can check\n    $json_url = isset( $_POST['import_url'] ) ? esc_url_raw( wp_unslash( $_POST['import_url'] ) ) : '';\n    $response = wp_remote_get($json_url, array(\n        'timeout'   => 60,\n        'sslverify' => false\n    ));\n    \u002F\u002F ... (truncated)\n});","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-post-kit\u002F4.0.21\u002Fadmin\u002Fadmin-biggopti.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-post-kit\u002F4.0.22\u002Fadmin\u002Fadmin-biggopti.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-post-kit\u002F4.0.21\u002Fadmin\u002Fadmin-biggopti.php\t2026-01-05 06:42:16.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-post-kit\u002F4.0.22\u002Fadmin\u002Fadmin-biggopti.php\t2026-01-12 12:41:24.000000000 +0000\n@@ -34,14 +34,6 @@\n \t * @return array|mixed\n \t *\u002F\n \tprivate function get_api_biggopties_data() {\n-\n-\t\t\u002F\u002F 6-hour transient cache for API response\n-\t\t$transient_key = 'bdt_api_biggopties';\n-\t\t$cached = get_transient($transient_key);\n-\t\tif ($cached !== false && is_array($cached)) {\n-\t\t\treturn $cached;\n-\t\t}\n-\n \t\t\u002F\u002F API endpoint for biggopties - you can change this to your actual endpoint\n \t\t$api_url = 'https:\u002F\u002Fapi.sigmative.io\u002Fprod\u002Fstore\u002Fapi\u002Fbiggopti\u002Fapi-data-records';\n \n@@ -63,8 +55,6 @@\n \t\tif( isset($biggopties) && isset($biggopties->{'ultimate-post-kit'}) ) {\n \t\t\t$data = $biggopties->{'ultimate-post-kit'};\n \t\t\tif (is_array($data)) {\n-\t\t\t\t$ttl = apply_filters('bdt_api_biggopties_cache_ttl', 6 * HOUR_IN_SECONDS);\n-\t\t\t\tset_transient($transient_key, $data, $ttl);\n \t\t\t\treturn $data;\n \t\t\t}\n \t\t}\n@@ -312,23 +302,41 @@\n \t\t\twp_send_json_error([ 'message' => 'forbidden' ]);\n \t\t}\n \n+\t\t\u002F\u002F Don't show biggopties on plugin\u002Ftheme install and upload pages\n+\t\t$current_url = isset($_POST['current_url']) ? sanitize_text_field($_POST['current_url']) : '';\n+\n+\t\tif (!empty($current_url)) {\n+\t\t\t$excluded_patterns = [\n+\t\t\t\t'plugin-install.php',\n+\t\t\t\t'theme-install.php',\n+\t\t\t\t'action=upload-plugin',\n+\t\t\t\t'action=upload-theme'\n+\t\t\t];\n+\n+\t\t\tforeach ($excluded_patterns as $pattern) {\n+\t\t\t\tif (strpos($current_url, $pattern) !== false) {\n+\t\t\t\t\twp_send_json_success([ 'html' => '' ]);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n \t\t$biggopties = $this->get_api_biggopties_data();\n \t\t$grouped_biggopties = [];\n \n \t\tif (is_array($biggopties)) {\n \t\t\tforeach ($biggopties as $index => $biggopti) {\n \t\t\t\tif ($this->should_show_biggopti($biggopti)) {\n-\t\t\t\t\t$biggopti_class = isset($biggopti->biggopti_class) ? $biggopti->biggopti_class : 'default-' . $index;\n-\t\t\t\t\tif (!isset($grouped_biggopties[$biggopti_class])) {\n-\t\t\t\t\t\t$grouped_biggopties[$biggopti_class] = $biggopti;\n+\t\t\t\t\t$display_id = isset($biggopti->display_id) ? $biggopti->display_id : 'default-' . $index;\n+\t\t\t\t\tif (!isset($grouped_biggopties[$display_id])) {\n+\t\t\t\t\t\t$grouped_biggopties[$display_id] = $biggopti;\n \t\t\t\t\t}\n \t\t\t\t}\n \t\t\t}\n \t\t}\n \n \t\t\u002F\u002F Build biggopties using the same pipeline as synchronous rendering\n-\t\tforeach ($grouped_biggopties as $biggopti_class => $biggopti) {\n-\t\t\t$biggopti_id = isset($biggopti->id) ? $biggopti_class : $biggopti->id;\n+\t\tforeach ($grouped_biggopties as $display_id => $biggopti) {\n+\t\t\t$biggopti_id = isset($biggopti->id) ? $display_id : $biggopti->id;\n \n \t\t\tself::add_biggopti([\n \t\t\t\t'id' => 'api-biggopti-' . $biggopti_id,\n@@ -374,6 +382,14 @@\n \t\t\t\tupdate_user_meta(get_current_user_id(), $id, true);\n \t\t\t} else {\n \t\t\t\tset_transient($id, true, $time);\n+\n+\t\t\t\t\u002F\u002F Also store in options table for persistence\n+\t\t\t\t$dismissals_option = get_option('bdt_biggopti_dismissals', []);\n+\t\t\t\t$dismissals_option[$id] = [\n+\t\t\t\t\t'dismissed_at' => time(),\n+\t\t\t\t\t'expires_at' => time() + intval($time),\n+\t\t\t\t];\n+\t\t\t\tupdate_option('bdt_biggopti_dismissals', $dismissals_option, false);\n \t\t\t}\n \n \t\t\twp_send_json_success();\n@@ -444,6 +460,22 @@\n \t\t\t\t$expired = get_user_meta(get_current_user_id(), $biggopti_id, true);\n \t\t\t} elseif ('transient' === $biggopti['dismissible-meta']) {\n \t\t\t\t$expired = get_transient($biggopti_id);\n+\n+\t\t\t\t\u002F\u002F If transient not found, check options table for persistent dismissal\n+\t\t\t\tif (false === $expired || empty($expired)) {\n+\t\t\t\t\t$dismissals_option = get_option('bdt_biggopti_dismissals', []);\n+\t\t\t\t\tif (isset($dismissals_option[$biggopti_id])) {\n+\t\t\t\t\t\t$dismissal = $dismissals_option[$biggopti_id];\n+\t\t\t\t\t\t\u002F\u002F Check if dismissal is still valid (not expired)\n+\t\t\t\t\t\tif (isset($dismissal['expires_at']) && time() \u003C $dismissal['expires_at']) {\n+\t\t\t\t\t\t\t$expired = true;\n+\t\t\t\t\t\t} else {\n+\t\t\t\t\t\t\t\u002F\u002F Clean up expired dismissal from options\n+\t\t\t\t\t\t\tunset($dismissals_option[$biggopti_id]);\n+\t\t\t\t\t\t\tupdate_option('bdt_biggopti_dismissals', $dismissals_option, false);\n+\t\t\t\t\t\t}\n+\t\t\t\t\t}\n+\t\t\t\t}\n \t\t\t}\n \n \t\t\t\u002F\u002F Biggopties visible after transient expire.\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-post-kit\u002F4.0.21\u002Fincludes\u002Fsetup-wizard\u002Finit.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-post-kit\u002F4.0.22\u002Fincludes\u002Fsetup-wizard\u002Finit.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-post-kit\u002F4.0.21\u002Fincludes\u002Fsetup-wizard\u002Finit.php\t2026-01-05 06:42:16.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fultimate-post-kit\u002F4.0.22\u002Fincludes\u002Fsetup-wizard\u002Finit.php\t2026-01-12 12:41:24.000000000 +0000\n@@ -412,9 +412,14 @@\n add_action('wp_ajax_import_elementor_template', function () {\n \t\tcheck_ajax_referer( 'setup_wizard_nonce', 'nonce' );\n \n+\t\tif ( ! current_user_can( 'manage_options' ) ) {\n+\t\t\twp_send_json_error( array( 'message' => esc_html__( 'Unauthorized', 'ultimate-post-kit' ) ) );\n+\t\t\twp_die();\n+\t\t}\n+\n \t\t$json_url = isset( $_POST['import_url'] ) ? esc_url_raw( wp_unslash( $_POST['import_url'] ) ) : '';\n \n-        $response = wp_remote_get($json_url, array(\n+        $response = wp_safe_remote_get($json_url, array(\n             'timeout'   => 60,\n             'sslverify' => false\n         ));\n@@ -502,6 +507,11 @@\n add_action('wp_ajax_import_upk_elementor_bundle_template', function () {\n     check_ajax_referer('setup_wizard_nonce', 'nonce');\n \n+\tif ( ! current_user_can( 'manage_options' ) ) {\n+        wp_send_json_error( array( 'message' => esc_html__( 'Unauthorized', 'ultimate-post-kit' ) ) );\n+        wp_die();\n+    }\n+\n     $file_url = isset($_POST['import_url']) ? esc_url_raw(wp_unslash($_POST['import_url'])) : '';\n \n     if (!filter_var($file_url, FILTER_VALIDATE_URL) || 0 !== strpos($file_url, 'http')) {\n@@ -592,6 +602,11 @@\n add_action('wp_ajax_import_upk_elementor_bundle_runner_template', function () {\n     check_ajax_referer('setup_wizard_nonce', 'nonce');\n \n+\tif ( ! current_user_can( 'manage_options' ) ) {\n+        wp_send_json_error( array( 'message' => esc_html__( 'Unauthorized', 'ultimate-post-kit' ) ) );\n+        wp_die();\n+    }\n+\n     $runner = isset($_POST['runner']) ? sanitize_text_field(wp_unslash($_POST['runner'])) : '';\n     $sessionId = isset($_POST['sessionId']) ? sanitize_text_field(wp_unslash($_POST['sessionId'])) : '';","The exploit targets the missing `current_user_can` checks in AJAX handlers that rely solely on nonces. \n\n1.  **Authentication**: The attacker authenticates as a low-privileged user (Subscriber).\n2.  **Nonce Acquisition**: The attacker visits the WordPress dashboard (e.g., `\u002Fwp-admin\u002Fprofile.php`). Because the plugin localizes script configurations for UI notices and the setup wizard globally in the admin area, nonces like `UltimatePostKitBiggoptiConfig.nonce` and `BDT_SetupWizard.nonce` are present in the page source.\n3.  **Unauthorized Action (API Fetch)**: The attacker sends a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with `action=upk_fetch_api_biggopties` and the acquired nonce. This forces the server to make a remote request to the Sigmative API and update the `bdt_api_biggopties` transient.\n4.  **Unauthorized Action (Template Import)**: The attacker sends a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with `action=import_elementor_template`, `import_url` (attacker-controlled URL), and the setup wizard nonce. The server will fetch the remote template data without verifying if the user has administrative privileges.","gemini-3-flash-preview","2026-04-18 02:43:49","2026-04-18 02:44:23",{"type":39,"vulnerable_version":40,"fixed_version":11,"vulnerable_browse":41,"vulnerable_zip":42,"fixed_browse":43,"fixed_zip":44,"all_tags":45},"plugin","4.0.21","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultimate-post-kit\u002Ftags\u002F4.0.21","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fultimate-post-kit.4.0.21.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultimate-post-kit\u002Ftags\u002F4.0.22","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fultimate-post-kit.4.0.22.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultimate-post-kit\u002Ftags"]