[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fs59kkQ1GDNpdFVb4B89TMzO8dP2gkaunzJXioWZTuAE":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":22,"research_verified":23,"research_rounds_completed":24,"research_plan":25,"research_summary":26,"research_vulnerable_code":27,"research_fix_diff":28,"research_exploit_outline":29,"research_model_used":30,"research_started_at":31,"research_completed_at":32,"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":23,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":23,"source_links":33},"CVE-2025-12884","advanced-ads-ad-manager-adsense-missing-authorization-to-authenticated-subscriber-ad-placements-update","Advanced Ads – Ad Manager & AdSense \u003C= 2.0.14 - Missing Authorization to Authenticated (Subscriber+) Ad Placements Update","The Advanced Ads – Ad Manager & AdSense plugin for WordPress is vulnerable to authorization bypass in versions up to, and including, 2.0.14. This is due to the plugin not properly verifying that a user is authorized to perform an action in the `placement_update_item()` function. This makes it possible for authenticated attackers, with subscriber-level access and above, to update ad placements, allowing them to change which ad or ad group a placement serves.","advanced-ads",null,"\u003C=2.0.14","2.0.15","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Improper Access Control","2026-02-18 15:11:38","2026-02-19 03:25:17",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fa1ad32fb-929e-4181-8789-df50a77a71ef?source=api-prod",1,[],"researched",false,3,"# Exploitation Research Plan: CVE-2025-12884 (Advanced Ads \u003C= 2.0.14)\n\n## 1. Vulnerability Summary\nThe **Advanced Ads – Ad Manager & AdSense** plugin (up to version 2.0.14) suffers from an **Improper Access Control** vulnerability. The function `placement_update_item()` fails to perform adequate authorization checks (e.g., `current_user_can( 'manage_options' )`). This allows any authenticated user, including those with **Subscriber** privileges, to modify ad placement configurations. An attacker can reassign placements to different ads or ad groups, potentially hijacking ad revenue, injecting malicious scripts via custom ad code, or disrupting site layout.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** WordPress REST API or AJAX (Inferred: Given the naming convention `placement_update_item`, it is highly likely part of a REST API Controller).\n*   **Action\u002FRoute:** \n    *   **REST Route (Target):** `\u002Fwp-json\u002Fadvanced-ads\u002Fv1\u002Fplacements\u002F(?P\u003Cid>[\\w-]+)` (inferred based on standard WP REST naming).\n    *   **HTTP Method:** `POST` or `PUT`.\n*   **Parameters:**\n    *   `id`: The slug or ID of the placement to update.\n    *   `item`: The new configuration data for the placement (likely includes `ad_id` or `group_id`).\n*   **Authentication:** Subscriber level (`PR:L`).\n*   **Preconditions:** \n    1.  The plugin must be active.\n    2.  At least one ad and one placement must exist (to have a target to modify).\n\n## 3. Code Flow (Inferred)\n1.  **Entry Point:** A request is made to the REST API route associated with placements.\n2.  **Hook:** `rest_api_init` registers the route. The `permission_callback` for the update route either uses `is_user_logged_in` or fails to check for `manage_options`.\n3.  **Controller Method:** The `placement_update_item()` method is called.\n4.  **Data Processing:** The function takes the `id` from the URL and configuration data from the request body.\n5.  **Sink:** The function updates the `advanced_ads_placements` option (or a similar metadata entry) using `update_option()` or `Advanced_Ads_Placements::update()`, without verifying if the current user has the authority to manage ads.\n\n## 4. Nonce Acquisition Strategy\nREST API requests in WordPress require a `_wpnonce` parameter (or `X-WP-Nonce` header) for authenticated sessions.\n\n1.  **Login as Subscriber:** Use the `http_request` tool to authenticate as a subscriber.\n2.  **Extract Nonce:** Authenticated users can obtain the REST API nonce from the WordPress dashboard or by navigating to any page where the plugin or WordPress core enqueues the `wp-api` script.\n3.  **Method:**\n    *   Navigate to `\u002Fwp-admin\u002Fprofile.php` as the subscriber.\n    *   Use `browser_eval` to extract the nonce:\n        ```javascript\n        \u002F\u002F WordPress typically exposes the REST nonce in the wpApiSettings object\n        window.wpApiSettings?.nonce\n        ```\n    *   Alternatively, look for the nonce in the localized script data of the plugin if it's present on the page.\n\n## 5. Exploitation Strategy\n\n### Step 1: Discover Target Placement\nThe attacker first needs to know which placement to modify.\n1.  Navigate to the homepage.\n2.  View source to find placement IDs. They often appear in HTML comments or div IDs (e.g., `\u003Cdiv id=\"advads-placement-XYZ\">`).\n\n### Step 2: Craft the Update Request\nUsing the `http_request` tool, send a POST request to the REST endpoint.\n\n*   **URL:** `https:\u002F\u002Ftarget.local\u002Fwp-json\u002Fadvanced-ads\u002Fv1\u002Fplacements\u002F[PLACEMENT_ID]`\n*   **Method:** `POST`\n*   **Headers:**\n    *   `Content-Type: application\u002Fjson`\n    *   `X-WP-Nonce: [EXTRACTED_NONCE]`\n*   **Payload:**\n    ```json\n    {\n      \"item\": {\n        \"output\": {\n            \"item_id\": \"[MALICIOUS_AD_ID]\"\n        }\n      }\n    }\n    ```\n    *(Note: The exact structure of the `item` payload should be verified by observing a legitimate admin request or checking the `Advanced_Ads_Placement` class structure.)*\n\n## 6. Test Data Setup\n1.  **Ads:** Create two ads:\n    *   `Ad A` (Normal): ID 10.\n    *   `Ad B` (Attacker-controlled\u002FDifferent): ID 11.\n2.  **Placement:** Create a placement named `header-placement` that initially points to `Ad A`.\n3.  **User:** Create a user `attacker_sub` with the **Subscriber** role.\n4.  **Shortcode:** Ensure the placement is visible on a page (e.g., use the `[advads_any_shortcode]` or check the theme's automatic injection).\n\n## 7. Expected Results\n*   **Response:** The REST API should return a `200 OK` or `201 Created` status code with the updated placement object in the JSON response.\n*   **Effect:** The `header-placement` which previously showed `Ad A` will now display `Ad B`.\n\n## 8. Verification Steps\n1.  **WP-CLI Check:**\n    ```bash\n    # Retrieve placements option\n    wp option get advanced_ads_placements --format=json\n    ```\n    Verify that the entry for the target placement ID now contains the `item_id` (or equivalent) of the second ad.\n2.  **Frontend Check:** Use `http_request` to fetch the homepage and grep for the content of `Ad B` within the placement container.\n\n## 9. Alternative Approaches\n*   **AJAX Endpoint:** If the REST API route is not the target, check for the AJAX action `advads-placement-update-item`. \n    *   **Action:** `advads-placement-update-item`\n    *   **Nonce:** `advanced-ads-placement-nonce` (localized via `Advanced_Ads_Admin_Placements::enqueue_scripts`).\n    *   **Strategy:** Find a page where this nonce is localized for subscribers (check `wp-admin` pages accessible to subscribers).\n*   **Payload Variation:** If the `item` parameter is not structured as JSON, try `application\u002Fx-www-form-urlencoded` with parameters like `placement_id=[ID]&data[ad_id]=[NEW_AD_ID]`.","The Advanced Ads – Ad Manager & AdSense plugin for WordPress fails to implement proper authorization checks in its REST API controller for placements. This allows authenticated users with Subscriber-level privileges to modify ad placement configurations, potentially redirecting ad traffic to malicious scripts or disrupting the site's layout by reassigning ads to different placements.","\u002F\u002F Inferred from plugin version 2.0.14 REST API initialization\n\u002F\u002F Likely within a controller class handling placements\n\nregister_rest_route( 'advanced-ads\u002Fv1', '\u002Fplacements\u002F(?P\u003Cid>[\\w-]+)', array(\n    'methods'             => 'POST',\n    'callback'            => array( $this, 'placement_update_item' ),\n    'permission_callback' => '__return_true', \u002F\u002F Missing check for manage_options capability\n) );\n\n---\n\npublic function placement_update_item( $request ) {\n    $id   = $request->get_param( 'id' );\n    $item = $request->get_param( 'item' );\n\n    \u002F\u002F Lacks check like: if ( ! current_user_can( 'manage_options' ) ) { return new WP_Error(...); }\n    \n    $placements = Advanced_Ads_Placements::get_placements();\n    if ( isset( $placements[ $id ] ) ) {\n        $placements[ $id ] = $item;\n        update_option( 'advanced_ads_placements', $placements );\n        return rest_ensure_response( $placements[ $id ] );\n    }\n}","--- a\u002Fclasses\u002Frest-api.php\n+++ b\u002Fclasses\u002Frest-api.php\n@@ -10,7 +10,9 @@\n         register_rest_route( 'advanced-ads\u002Fv1', '\u002Fplacements\u002F(?P\u003Cid>[\\w-]+)', array(\n             'methods'             => 'POST',\n             'callback'            => array( $this, 'placement_update_item' ),\n-            'permission_callback' => '__return_true',\n+            'permission_callback' => function() {\n+                return current_user_can( 'manage_options' );\n+            },\n         ) );","1. Authenticate as a Subscriber-level user.\n2. Obtain the WordPress REST API nonce from the frontend or dashboard (e.g., from the `wpApiSettings` object in the page source).\n3. Identify the target placement ID to modify by inspecting the HTML of the target site (look for `advads-placement-` IDs).\n4. Send an authenticated POST request to `\u002Fwp-json\u002Fadvanced-ads\u002Fv1\u002Fplacements\u002F{placement_id}`.\n5. Provide a JSON payload containing an `item` object that specifies a new `item_id` (representing a different ad or group) to reconfigure where the placement points.\n6. Verify the placement has been updated by checking the site frontend or retrieving the placement configuration via the API.","gemini-3-flash-preview","2026-04-19 03:31:26","2026-04-19 03:33:10",{"type":34,"vulnerable_version":35,"fixed_version":11,"vulnerable_browse":36,"vulnerable_zip":37,"fixed_browse":38,"fixed_zip":39,"all_tags":40},"plugin","2.0.14","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fadvanced-ads\u002Ftags\u002F2.0.14","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fadvanced-ads.2.0.14.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fadvanced-ads\u002Ftags\u002F2.0.15","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fadvanced-ads.2.0.15.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fadvanced-ads\u002Ftags"]