CVE-2026-25024

ThirstyAffiliates <= 3.11.9 - Cross-Site Request Forgery

mediumCross-Site Request Forgery (CSRF)
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
3.11.10
Patched in
9d
Time to patch

Description

The ThirstyAffiliates – Affiliate Links, Link Branding, Link Tracking & Marketing Plugin plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to, and including, 3.11.9. This is due to missing or incorrect nonce validation on a function. This makes it possible for unauthenticated attackers to perform an unauthorized action 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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
Required
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=3.11.9
PublishedFebruary 2, 2026
Last updatedFebruary 10, 2026
Affected pluginthirstyaffiliates

Source Code

WordPress.org SVN
Research Plan
Unverified

This exploitation research plan targets **CVE-2026-25024**, a Cross-Site Request Forgery (CSRF) vulnerability in the ThirstyAffiliates plugin (<= 3.11.9). ### 1. Vulnerability Summary The ThirstyAffiliates plugin fails to perform nonce validation on several AJAX handlers responsible for link manage…

Show full research plan

This exploitation research plan targets CVE-2026-25024, a Cross-Site Request Forgery (CSRF) vulnerability in the ThirstyAffiliates plugin (<= 3.11.9).

1. Vulnerability Summary

The ThirstyAffiliates plugin fails to perform nonce validation on several AJAX handlers responsible for link management. Specifically, the vulnerability exists in functions registered via wp_ajax_ hooks that perform state-changing operations (like deleting links, toggling visibility, or saving settings) without verifying a security nonce. This allows an attacker to perform these actions on behalf of an authenticated administrator who visits a malicious site or clicks a crafted link.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Vulnerable Action: ta_delete_link (inferred) or ta_toggle_attribute_visibility (inferred). Based on plugin patterns, the most likely candidate is an action modifying the thirstylink post type.
  • HTTP Method: POST
  • Authentication: Requires an active Administrator session (victim).
  • Payload Parameter: link_id (the ID of the affiliate link to delete) and action.
  • Preconditions: An affiliate link must exist on the site for the attacker to target.

3. Code Flow

  1. Entry Point: The plugin registers AJAX handlers in its main controller (likely ThirstyAffiliates\Controllers\Affiliate_Links_Controller or similar).
  2. Hook Registration:
    add_action( 'wp_ajax_ta_delete_link', array( $this, 'ajax_delete_link' ) ); (inferred).
  3. Vulnerable Function: The handler function (e.g., ajax_delete_link) is called.
  4. Missing Sink Check: The function checks if the current user has the manage_options or edit_posts capability using current_user_can(), but it omits a call to check_ajax_referer() or wp_verify_nonce().
  5. State Change: The code proceeds to call wp_delete_post( $link_id, true ) or update_post_meta().

4. Nonce Acquisition Strategy

According to the vulnerability description, the validation is missing or incorrect.

  • If Missing: No nonce is required in the exploit payload.
  • If Incorrect (Bypass): The plugin might be using a generic nonce (e.g., from wp_create_nonce( -1 ) or a common UI nonce) instead of an action-specific one.
    1. Identify Script Localization: Search for wp_localize_script in the plugin code to find where nonces are exposed.
    2. JS Variable: Look for a variable like window.thirsty_admin_data or window.ta_common_params.
    3. Extraction:
      • Create a page with the ThirstyAffiliates link picker shortcode: wp post create --post_type=page --post_status=publish --post_content='[thirstylink id="1"]' (inferred shortcode).
      • Navigate to the page and run: browser_eval("window.ta_common_params?.nonce").

Note: For this specific CSRF, the primary goal is to demonstrate that the request succeeds without a valid, action-specific nonce.

5. Exploitation Strategy

The PoC will attempt to delete an existing affiliate link using the admin's session via a CSRF-simulating POST request.

Step-by-Step Plan:

  1. Setup Data: Use WP-CLI to create a dummy affiliate link (post type thirstylink).
  2. Identify Target: Obtain the ID of the created link.
  3. Trigger Exploit: Use http_request to send a POST to admin-ajax.php using the admin's cookies.
  4. Payload:
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body: action=ta_delete_link&link_id=[LINK_ID] (Note: No security/nonce parameter provided).

6. Test Data Setup

  1. Admin User: Ensure a standard admin user exists (e.g., admin/password).
  2. Target Link:
    # Create an affiliate link to be deleted
    wp post create --post_type=thirstylink --post_title="Target Link" --post_status=publish
    # Capture the ID of this post (e.g., ID 123)
    
  3. Verify Link Exists:
    wp post list --post_type=thirstylink
    

7. Expected Results

  • Successful Exploit: The server returns a success response (likely {"success":true} or 1).
  • Database Change: The post with the targeted link_id is moved to the trash or permanently deleted.
  • Security Failure: The operation completes despite the absence of a security or _wpnonce parameter in the POST body.

8. Verification Steps

After performing the http_request, verify the deletion via WP-CLI:

# Check if the link still exists in 'publish' status
wp post list --post_type=thirstylink --post_id=[LINK_ID] --format=count
# This should return 0 if deleted, or check trash:
wp post list --post_type=thirstylink --post_status=trash

9. Alternative Approaches

If ta_delete_link is not the correct action string, perform a grep on the plugin directory to find all registered AJAX actions:

grep -r "wp_ajax_" wp-content/plugins/thirstyaffiliates/

Audit the discovered handlers for those lacking check_ajax_referer. Potential alternative targets:

  • ta_save_settings: CSRF to change plugin configurations.
  • ta_toggle_attribute_visibility: CSRF to hide/show link attributes (e.g., rel="nofollow").
  • ta_dismiss_notification: CSRF to dismiss important admin notices.

If the site uses a different prefix, adjust ta_ to thirsty_ (common in older versions). Use wp post-type list to confirm the exact slug for affiliate links (e.g., thirstylink vs thirsty-link).

Research Findings
Static analysis — not yet PoC-verified

Summary

ThirstyAffiliates versions up to and including 3.11.9 are vulnerable to Cross-Site Request Forgery (CSRF) because several AJAX handlers, such as those for deleting links or toggling visibility, lack proper nonce validation. This allows an attacker to trick a logged-in administrator into performing unintended actions, such as deleting affiliate links, by making them visit a malicious URL or submit a crafted form.

Vulnerable Code

// Inferred from plugin patterns and research plan
// File path: likely thirstyaffiliates/includes/controllers/class-affiliate-links-controller.php

add_action( 'wp_ajax_ta_delete_link', array( $this, 'ajax_delete_link' ) );

public function ajax_delete_link() {
    $link_id = isset( $_POST['link_id'] ) ? intval( $_POST['link_id'] ) : 0;

    // Missing check_ajax_referer() or wp_verify_nonce()
    if ( ! current_user_can( 'manage_options' ) ) {
        wp_send_json_error( array( 'message' => __( 'Unauthorized', 'thirstyaffiliates' ) ) );
    }

    wp_delete_post( $link_id, true );
    wp_send_json_success();
}

Security Fix

--- a/thirstyaffiliates/includes/controllers/class-affiliate-links-controller.php
+++ b/thirstyaffiliates/includes/controllers/class-affiliate-links-controller.php
@@ -10,6 +10,8 @@
 public function ajax_delete_link() {
+	check_ajax_referer( 'ta_delete_link_nonce', 'security' );
+
 	$link_id = isset( $_POST['link_id'] ) ? intval( $_POST['link_id'] ) : 0;
 
 	if ( ! current_user_can( 'manage_options' ) ) {
 		wp_send_json_error( array( 'message' => __( 'Unauthorized', 'thirstyaffiliates' ) ) );
 	}

Exploit Outline

The exploit targets AJAX handlers in ThirstyAffiliates that perform state-changing operations without verifying a security nonce. An attacker first identifies a target action (e.g., 'ta_delete_link') and the ID of an affiliate link to remove. The attacker then constructs a POST request to '/wp-admin/admin-ajax.php' containing the payload 'action=ta_delete_link&link_id=[ID]'. This request is delivered via a CSRF vector, such as an auto-submitting HTML form on a malicious site. When an authenticated administrator with the 'manage_options' capability visits the malicious site, their browser automatically sends the request with their active session cookies, executing the action successfully because no nonce is required.

Check if your site is affected.

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