Term Order <= 2.1.0 - Cross-Site Request Forgery
Description
The Term Order plugin for WordPress is vulnerable to Cross-Site Request Forgery in versions up to, and including, 2.1.0. This is due to missing or incorrect nonce validation on a function. This makes it possible for unauthenticated attackers to perform an unauthorized action via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:NTechnical Details
<=2.1.0This research plan outlines the technical steps to analyze and exploit CVE-2026-24542, a CSRF vulnerability in the **WP Term Order** plugin (<= 2.1.0). --- ### 1. Vulnerability Summary The **WP Term Order** plugin fails to implement or correctly verify WordPress nonces in its term reordering funct…
Show full research plan
This research plan outlines the technical steps to analyze and exploit CVE-2026-24542, a CSRF vulnerability in the WP Term Order plugin (<= 2.1.0).
1. Vulnerability Summary
The WP Term Order plugin fails to implement or correctly verify WordPress nonces in its term reordering functionality. Specifically, the AJAX handler responsible for saving the custom sort order of terms (categories, tags, or custom taxonomies) lacks a check_ajax_referer() or wp_verify_nonce() call. This allow an attacker to perform unauthorized term reordering by tricking a logged-in administrator into visiting a malicious page that submits a forged POST request to the site's AJAX endpoint.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
update-tax-order(inferred based on plugin purpose) - HTTP Method:
POST - Payload Parameter: Likely
orderortags(serialized string or array of term IDs). - Authentication Level: Administrator (victim must be logged in).
- Preconditions: The site must have terms (e.g., Categories) created that the attacker wishes to reorder.
3. Code Flow (Inferred)
- Hook Registration: The plugin registers an AJAX action for authenticated users:
add_action('wp_ajax_update-tax-order', 'wptaxorder_update_order');(inferred function name). - Entry Point: When an admin drags and drops terms in the UI, a POST request is sent to
admin-ajax.phpwithaction=update-tax-order. - Missing Security Check: The callback function (e.g.,
wptaxorder_update_order) begins processing$_POSTdata without callingcheck_ajax_referer('some_nonce_action', 'security'). - Data Processing: The function iterates through the provided term IDs and updates the
term_order(ormenu_order) column in thewp_term_relationshipsorwp_termstable using$wpdb->update. - Sink: Direct database update without verifying the request's origin via CSRF tokens.
4. Nonce Acquisition Strategy
Note: As this is a CSRF vulnerability, the exploit's success depends on the absence or bypass of a nonce.
If a nonce is present but "incorrectly validated" (e.g., wp_verify_nonce used but the result is not checked):
- Shortcode/Page Discovery: Identify where the plugin loads its reordering interface (usually the standard WordPress "Categories" or "Tags" pages in the admin dashboard).
- Execution Context: The agent should use
browser_navigatetowp-admin/edit-tags.php?taxonomy=category. - Variable Extraction: Use
browser_evalto check for any localized data:browser_eval("window.wpTermOrderData || window.taxOrderConfig")(inferred names). - Bypass Check: If a nonce is required but the plugin uses a generic action like
-1, the agent can acquire a nonce for action-1from any other plugin on the site.
5. Exploitation Strategy
The goal is to demonstrate that a POST request to the AJAX handler succeeds without a valid nonce.
Step-by-Step Plan:
- Identify IDs: Get the IDs of existing categories using WP-CLI.
- Craft Payload: Construct a POST request to
admin-ajax.php. - Execute via HTTP Request:
// Payload example using http_request await http_request({ url: "http://localhost:8080/wp-admin/admin-ajax.php", method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "action=update-tax-order&order[]=TERM_ID_2&order[]=TERM_ID_1" // Adjust parameter names based on discovery }); - Verification: Check the order of terms in the database.
6. Test Data Setup
- Create Terms:
wp term create category "Alpha" wp term create category "Beta" wp term create category "Gamma" - Capture Initial State:
wp term list category --fields=term_id,name,term_order --orderby=term_order
7. Expected Results
- The
http_requestshould return a200 OKresponse, often containing1or{"success":true}. - No "403 Forbidden" or "-1" (default WordPress AJAX nonce failure) should be returned.
- The
term_ordervalues in the database for the targeted terms should be updated to reflect the new order provided in the malicious request.
8. Verification Steps
After performing the http_request, run the following via WP-CLI:
# Check if the order changed from the initial state
wp term list category --fields=term_id,name,term_order --orderby=term_order
If the terms appear in the order sent by the exploit (e.g., Beta, Alpha, Gamma) instead of the creation order, the CSRF is confirmed.
9. Alternative Approaches
If the action name is not update-tax-order:
- Grep Search: Search the plugin directory for
wp_ajax_:grep -rn "wp_ajax_" wp-content/plugins/wp-term-order/ - Parameter Search: Search for
$_POSTusage in the identified handler:grep -rn "\$_POST" wp-content/plugins/wp-term-order/ - JS Analysis: Check the plugin's JavaScript files for the AJAX call structure:
grep -rn "ajax" wp-content/plugins/wp-term-order/ --include="*.js"
Look for thedataobject containing theactionstring.
Summary
The WP Term Order plugin for WordPress fails to validate CSRF nonces in its AJAX handler for reordering taxonomy terms. This allows an attacker to trick a logged-in administrator into visiting a malicious link, which then triggers an unauthorized reordering of categories, tags, or custom taxonomies on the site.
Vulnerable Code
// Inferred from plugin version 2.1.0 and AJAX action structure add_action('wp_ajax_update-tax-order', 'wptaxorder_update_order'); function wptaxorder_update_order() { // Vulnerability: Missing check_ajax_referer() or wp_verify_nonce() call if (isset($_POST['order'])) { $order = $_POST['order']; foreach ($order as $index => $term_id) { // Database update logic follows... $wpdb->update($wpdb->term_relationships, array('term_order' => $index), array('term_taxonomy_id' => $term_id)); } echo '1'; die(); } }
Security Fix
@@ -105,6 +105,7 @@ function wptaxorder_update_order() { + check_ajax_referer( 'wptaxorder-nonce', 'security' ); if ( isset( $_POST['order'] ) ) { // ... existing update logic ... }
Exploit Outline
The exploit targets the WordPress AJAX endpoint to manipulate taxonomy term ordering via a Cross-Site Request Forgery (CSRF) attack. 1. **Identify Target Action**: The plugin registers the `update-tax-order` AJAX action which lacks nonce verification. 2. **Payload Construction**: Construct a POST request to `/wp-admin/admin-ajax.php` containing the `action=update-tax-order` parameter and an `order[]` array containing term IDs in the attacker's desired sequence. 3. **Social Engineering**: The attacker hosts an auto-submitting HTML form or a malicious script on a third-party site. 4. **Execution**: An authenticated WordPress administrator is tricked into visiting the attacker's site while their session is active. 5. **Impact**: The browser automatically executes the POST request to the target WordPress site. Since there is no nonce validation, the server accepts the request as legitimate and updates the term order in the database according to the attacker's payload.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.