ThirstyAffiliates <= 3.11.9 - Cross-Site Request Forgery
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:NTechnical Details
<=3.11.9Source Code
WordPress.org SVNThis 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) orta_toggle_attribute_visibility(inferred). Based on plugin patterns, the most likely candidate is an action modifying thethirstylinkpost type. - HTTP Method:
POST - Authentication: Requires an active Administrator session (victim).
- Payload Parameter:
link_id(the ID of the affiliate link to delete) andaction. - Preconditions: An affiliate link must exist on the site for the attacker to target.
3. Code Flow
- Entry Point: The plugin registers AJAX handlers in its main controller (likely
ThirstyAffiliates\Controllers\Affiliate_Links_Controlleror similar). - Hook Registration:
add_action( 'wp_ajax_ta_delete_link', array( $this, 'ajax_delete_link' ) );(inferred). - Vulnerable Function: The handler function (e.g.,
ajax_delete_link) is called. - Missing Sink Check: The function checks if the current user has the
manage_optionsoredit_postscapability usingcurrent_user_can(), but it omits a call tocheck_ajax_referer()orwp_verify_nonce(). - State Change: The code proceeds to call
wp_delete_post( $link_id, true )orupdate_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.- Identify Script Localization: Search for
wp_localize_scriptin the plugin code to find where nonces are exposed. - JS Variable: Look for a variable like
window.thirsty_admin_dataorwindow.ta_common_params. - 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").
- Create a page with the ThirstyAffiliates link picker shortcode:
- Identify Script Localization: Search for
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:
- Setup Data: Use WP-CLI to create a dummy affiliate link (post type
thirstylink). - Identify Target: Obtain the ID of the created link.
- Trigger Exploit: Use
http_requestto send a POST toadmin-ajax.phpusing the admin's cookies. - 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).
- URL:
6. Test Data Setup
- Admin User: Ensure a standard admin user exists (e.g.,
admin/password). - 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) - Verify Link Exists:
wp post list --post_type=thirstylink
7. Expected Results
- Successful Exploit: The server returns a success response (likely
{"success":true}or1). - Database Change: The post with the targeted
link_idis moved to the trash or permanently deleted. - Security Failure: The operation completes despite the absence of a
securityor_wpnonceparameter 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).
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
@@ -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.