[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f2EtsUFUC5XdKUDFo3jKSw296npjqQCVGwyV1Yjv6Ovw":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":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"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":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-34903","ocean-extra-missing-authorization","Ocean Extra \u003C= 2.5.3 - Missing Authorization","The Ocean Extra plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 2.5.3. This makes it possible for authenticated attackers, with Subscriber-level access and above, to perform an unauthorized action.","ocean-extra",null,"\u003C=2.5.3","2.5.4","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-04-07 00:00:00","2026-04-15 19:48:14",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F24347126-56f5-4fb2-afcd-52af0b879eb0?source=api-prod",9,[22,23,24,25,26,27,28,29],"changelog.txt","includes\u002Fonboarding\u002Fclass\u002Fimport-data.php","includes\u002Fonboarding\u002Finstall-demo\u002Fstart.php","includes\u002Fonboarding\u002Fsetup-wizard\u002Fstart.php","includes\u002Fonboarding\u002Fstart.php","languages\u002Focean-extra.pot","ocean-extra.php","readme.txt","researched",false,3,"# Research Plan: CVE-2026-34903 - Ocean Extra Missing Authorization\n\n## 1. Vulnerability Summary\nThe **Ocean Extra** plugin (\u003C= 2.5.3) contains a missing authorization vulnerability in its Onboarding\u002FDemo Import logic. Specifically, the class `OE_Onboarding_Site_Templates_Import_Data` registers several AJAX actions that lack capability checks (`current_user_can`). While these actions verify a WordPress nonce for CSRF protection, the nonce is available to any authenticated user (including Subscribers) in the WordPress admin dashboard. This allows a Subscriber-level attacker to trigger administrative actions such as downloading template files, deleting specific posts, and importing demo data.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action**: `oceanwp_onboarding_import_data` (registered in `includes\u002Fonboarding\u002Fclass\u002Fimport-data.php`)\n- **Vulnerable Parameters**: \n    - `action`: `oceanwp_onboarding_import_data`\n    - `nonce`: The `owp-onboarding` nonce.\n    - `importType`: `content`, `customizer`, `widgets`, or `form`.\n- **Authentication**: Authenticated (Subscriber and above).\n- **Preconditions**: The plugin must be active, and a valid nonce must be retrieved from the admin area.\n\n## 3. Code Flow\n1.  **Nonce Generation**: `OE_Onboarding_Manager::localize_script()` (in `includes\u002Fonboarding\u002Fstart.php`) creates a nonce:\n    ```php\n    'nonce' => wp_create_nonce( 'owp-onboarding' ),\n    ```\n2.  **Nonce Exposure**: This nonce is localized to the script `oe-onboarding` via `wp_localize_script` under the object name `oeOnboardingLoc`. The scripts are enqueued via the `admin_enqueue_scripts` hook, which runs for any user logged into the WordPress dashboard.\n3.  **AJAX Registration**: In `includes\u002Fonboarding\u002Fclass\u002Fimport-data.php`, the `__construct()` method registers the AJAX handlers:\n    ```php\n    add_action( 'wp_ajax_oceanwp_onboarding_import_data', array( $this, 'onboarding_import_data' ) );\n    ```\n4.  **Vulnerable Handler**: The function `onboarding_import_data()` performs a nonce check but fails to perform an authorization check:\n    ```php\n    public function onboarding_import_data() {\n        if ( !isset($_POST['nonce']) || !wp_verify_nonce( sanitize_key($_POST['nonce']), 'owp-onboarding' ) ) {\n            wp_send_json_error([...]);\n        }\n        \u002F\u002F ... (Missing current_user_can('manage_options')) ...\n        $import_type = isset($_POST['importType']) ? sanitize_text_field($_POST['importType']) : '';\n        \u002F\u002F ...\n        switch ($import_type) {\n            case 'content':\n                $result = $this->import_content($template);\n                break;\n            \u002F\u002F ...\n        }\n    }\n    ```\n5.  **Sink**: `import_content($template)` (in the same file) proceeds to delete standard WordPress posts:\n    ```php\n    $sample_page      = get_page_by_path( 'sample-page', OBJECT, 'page' );\n    $hello_world_post = get_page_by_path( 'hello-world', OBJECT, 'post' );\n    if ( ! is_null( $sample_page ) ) {\n        wp_delete_post( $sample_page->ID, true );\n    }\n    ```\n\n## 4. Nonce Acquisition Strategy\nThe nonce is localized in the WordPress admin dashboard for all authenticated users.\n1.  **Navigation**: Navigate to `\u002Fwp-admin\u002Findex.php` as a Subscriber.\n2.  **Extraction**: Use `browser_eval` to extract the nonce from the global JavaScript object `oeOnboardingLoc`.\n    - **JS Command**: `window.oeOnboardingLoc?.nonce`\n\n## 5. Exploitation Strategy\n1.  **Auth**: Log in as a Subscriber-level user.\n2.  **Setup**: The handler requires the option `ocean_installing_template_data` to be set. Since the focus is demonstrating the lack of authorization on the AJAX handler, we will simulate the \"Template Selection\" step by setting this option via CLI, or verify if the handler reaches the `wp_verify_nonce` check.\n3.  **Request**: Send a POST request to `admin-ajax.php`.\n    - **URL**: `http:\u002F\u002Flocalhost:8888\u002Fwp-admin\u002Fadmin-ajax.php`\n    - **Method**: POST\n    - **Headers**: `Content-Type: application\u002Fx-www-form-urlencoded`\n    - **Body**:\n        ```\n        action=oceanwp_onboarding_import_data&nonce=[NONCE]&importType=content\n        ```\n4.  **Action**: The execution will trigger the `import_content` method. This method automatically attempts to delete the default \"Hello World\" post and \"Sample Page\".\n\n## 6. Test Data Setup\n1.  **User**: Create a user with the `subscriber` role.\n2.  **Target Content**: Ensure a post with slug `hello-world` exists (standard in default WP).\n3.  **State Setup**: Set the required option for the importer to proceed:\n    ```bash\n    wp option update ocean_installing_template_data '{\"slug\":\"coach\",\"content\":true}' --format=json\n    ```\n    *(Note: This simulates the attacker or a previous admin selecting a demo template to import).*\n\n## 7. Expected Results\n- The AJAX request should return a JSON response.\n- If the import fails due to connectivity to `demos.oceanwp.org`, the `import_content` logic will **still** execute the `wp_delete_post` calls before the external fetch, confirming unauthorized modification of site content.\n- The \"Hello World\" post will be permanently deleted from the database.\n\n## 8. Verification Steps\n1.  **Check Post Existence**:\n    ```bash\n    wp post list --name=\"hello-world\" --post_type=post\n    ```\n    If the post is no longer listed, the unauthorized action was successful.\n2.  **Verify Capability Check**: Attempt the same request as an unauthenticated user; it should fail the nonce check. Attempt as a Subscriber; it should pass the nonce check and proceed to the logic.\n\n## 9. Alternative Approaches\nIf `importType=content` fails or is blocked by environmental factors:\n- **Action**: `download_selected_template_data`\n- **Body**: `action=download_template_data&security=[NONCE]`\n- **Effect**: This calls `download_template_files`, which makes remote requests (SSRF-lite) and updates the option `ocean_downloaded_demo_path`.\n- **Verification**: `wp option get ocean_downloaded_demo_path` to see if it was updated by the Subscriber's request.","The Ocean Extra plugin for WordPress is vulnerable to unauthorized data modification and administrative action execution due to missing capability checks on several AJAX handlers in the onboarding and demo import logic. This allows authenticated attackers with Subscriber-level access to trigger demo data imports, download template files, or delete default site content like posts and pages.","\u002F\u002F includes\u002Fonboarding\u002Fclass\u002Fimport-data.php line 60\n        public function download_selected_template_data() {\n\n            check_ajax_referer('owp-onboarding', 'security');\n\n            $template = get_option('ocean_installing_template_data');\n---\n\u002F\u002F includes\u002Fonboarding\u002Fclass\u002Fimport-data.php line 131\n        public function onboarding_import_data() {\n\n            if ( !isset($_POST['nonce']) || !wp_verify_nonce( sanitize_key($_POST['nonce']), 'owp-onboarding' ) ) {\n                wp_send_json_error(array(\n                    'message' => __('Nonce verification failed.', 'ocean-extra')\n                ));\n            }\n\n            $template = get_option('ocean_installing_template_data');\n---\n\u002F\u002F includes\u002Fonboarding\u002Fstart.php line 228\n\t\t\treturn apply_filters(\n\t\t\t\t'ocean_onboarding_localize',\n\t\t\t\t[\n\t\t\t\t\t'options' => oe_onboarding_wizard_options(),\n\t\t\t\t\t'childThemeStatus' => $child_theme_status,\n\t\t\t\t\t'siteUrl' => esc_url(site_url()),\n\t\t\t\t\t'homeUrl' => esc_url(home_url()),\n\t\t\t\t\t'adminUrl' => esc_url(admin_url()),\n\t\t\t\t\t'nonce' => wp_create_nonce( 'owp-onboarding' ),\n\t\t\t\t\t'ajax_url' => admin_url( 'admin-ajax.php' ),","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Focean-extra\u002F2.5.3\u002Fincludes\u002Fonboarding\u002Fclass\u002Fimport-data.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Focean-extra\u002F2.5.4\u002Fincludes\u002Fonboarding\u002Fclass\u002Fimport-data.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Focean-extra\u002F2.5.3\u002Fincludes\u002Fonboarding\u002Fclass\u002Fimport-data.php\t2026-02-16 09:30:20.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Focean-extra\u002F2.5.4\u002Fincludes\u002Fonboarding\u002Fclass\u002Fimport-data.php\t2026-03-09 09:02:10.000000000 +0000\n@@ -64,6 +64,15 @@\n \n             check_ajax_referer('owp-onboarding', 'security');\n \n+            if ( ! current_user_can( 'manage_options' ) ) {\n+                wp_send_json_error(\n+                    array(\n+                        'message' => __( 'You do not have permission to perform this action.', 'ocean-extra' )\n+                    ),\n+                    403\n+                );\n+            }\n+\n             $template = get_option('ocean_installing_template_data');\n \n             if (empty($template)) {\n@@ -132,6 +141,15 @@\n                 ));\n             }\n \n+            if ( ! current_user_can( 'manage_options' ) ) {\n+                wp_send_json_error(\n+                    array(\n+                        'message' => __( 'You do not have permission to perform this action.', 'ocean-extra' )\n+                    ),\n+                    403\n+                );\n+            }\n+\n             $template = get_option('ocean_installing_template_data');\n \n             if (empty($template)) {\n@@ -385,6 +403,15 @@\n                 ));\n             }\n \n+            if ( ! current_user_can( 'manage_options' ) ) {\n+                wp_send_json_error(\n+                    array(\n+                        'message' => __( 'You do not have permission to perform this action.', 'ocean-extra' )\n+                    ),\n+                    403\n+                );\n+            }\n+\n             $template = get_option('ocean_installing_template_data');\n \n             if ( empty( $template ) ) {","An attacker with Subscriber-level privileges can exploit this vulnerability through the following steps:\n1. Log in to the WordPress admin dashboard as a Subscriber.\n2. Locate the global JavaScript object `oeOnboardingLoc` (localized by the plugin for all authenticated users) and extract the value of the `nonce` key, which uses the action string 'owp-onboarding'.\n3. Send an AJAX POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the action set to `oceanwp_onboarding_import_data` or `download_template_data`.\n4. Include the extracted nonce in the `nonce` or `security` parameter respectively.\n5. To delete standard content, use the `importType=content` parameter. The server-side logic in `import_content` will proceed to call `wp_delete_post` for the 'sample-page' and 'hello-world' slugs without verifying if the user has administrative permissions.","gemini-3-flash-preview","2026-04-17 21:15:38","2026-04-17 21:16:15",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","2.5.3","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Focean-extra\u002Ftags\u002F2.5.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Focean-extra.2.5.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Focean-extra\u002Ftags\u002F2.5.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Focean-extra.2.5.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Focean-extra\u002Ftags"]