Delicious <= 1.9.5 - Missing Authorization
Description
The Delicious plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.9.5. 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:NTechnical Details
<=1.9.5Source Code
WordPress.org SVNPatched version not available.
This research plan targets **CVE-2026-39528**, a Missing Authorization vulnerability in the **WP Delicious** plugin (formerly Delicious Recipes). With a CVSS of 5.3, the vulnerability likely allows unauthenticated users to perform actions that should be restricted, such as submitting ratings, modify…
Show full research plan
This research plan targets CVE-2026-39528, a Missing Authorization vulnerability in the WP Delicious plugin (formerly Delicious Recipes). With a CVSS of 5.3, the vulnerability likely allows unauthenticated users to perform actions that should be restricted, such as submitting ratings, modifying a global counter, or interacting with user-specific data (like wishlists) without proper verification.
1. Vulnerability Summary
- Vulnerability: Missing Authorization
- Plugin: WP Delicious – Recipe Plugin for Food Bloggers (
delicious-recipes) - Affected Versions: <= 1.9.5
- Patched Version: 1.9.6
- Core Issue: An AJAX handler registered via
wp_ajax_nopriv_fails to perform a capability check (current_user_can()) or incorrectly validates the ownership of the resource being modified. This allows any unauthenticated visitor to trigger the function and perform unauthorized actions.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - HTTP Method: POST
- Authentication: None (Unauthenticated)
- Action Candidates (to be verified via grep):
delicious_recipes_rating(Submit/Modify ratings)delicious_recipes_like_dislike(Modify like counts)delicious_recipes_add_to_wishlist(If it lacks a check for the target user ID)delicious_recipes_social_share_count(Update share metrics)
- Preconditions: The plugin must be active. Some actions may require a valid
post_id(a published recipe).
3. Code Flow (Inferred)
- Entry Point: The plugin registers a
noprivAJAX action:add_action( 'wp_ajax_nopriv_[ACTION_NAME]', array( $this, '[CALLBACK_FUNCTION]' ) ); - Execution: When a POST request is sent to
admin-ajax.php?action=[ACTION_NAME], WordPress executes the[CALLBACK_FUNCTION]. - The Sink: Inside the
[CALLBACK_FUNCTION], the code likely performs a database update (e.g.,update_post_meta,wpdb->update, orupdate_user_meta) based on user-supplied parameters ($_POST['post_id'],$_POST['rating'], etc.). - The Flaw: The function lacks a
current_user_can()check or fails to verify a nonce that is strictly bound to an authorized session, allowing unauthenticated modification of metadata or settings.
4. Nonce Acquisition Strategy
If the handler uses check_ajax_referer or wp_verify_nonce, the nonce is likely exposed via wp_localize_script.
- Identify Script: The plugin typically enqueues scripts for recipes.
- Create Content: Create a recipe post to ensure scripts are loaded.
wp post create --post_type=recipes --post_title="Vuln Test Recipe" --post_status=publish --post_content="Delicious Recipe Content" - Locate Nonce:
- Search for
wp_localize_scriptin the plugin source to find the variable name. - Common JS object:
delicious_recipes_paramsordr_recipes_obj. - Common Nonce Key:
nonceorajax_nonce.
- Search for
- Extraction (Agent Step):
- Navigate to the newly created recipe page.
- Run:
browser_eval("window.delicious_recipes_params?.nonce")(Verify variable name in source first).
5. Exploitation Strategy
The goal is to perform an unauthorized state change (e.g., artificially inflating a recipe's rating or like count).
- Discovery: Find the vulnerable action.
grep -rn "wp_ajax_nopriv_" wp-content/plugins/delicious-recipes/
Check the callback functions for a lack ofcurrent_user_can(). - Identify Parameters: Look at the callback function to see which
$_POSTvariables are used (e.g.,post_id,rating,type). - Craft Request:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method: POST
- Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=[VULNERABLE_ACTION]&nonce=[EXTRACTED_NONCE]&post_id=[ID]&[OTHER_PARAMS]=[VALUE]
- URL:
- Execution: Use
http_requestto send the payload.
6. Test Data Setup
- Plugin Installation: Ensure WP Delicious <= 1.9.5 is installed and active.
- Target Content:
# Create a recipe to target wp post create --post_type=recipes --post_title="Target Recipe" --post_status=publish # Get the ID of the created recipe TARGET_ID=$(wp post list --post_type=recipes --post_title="Target Recipe" --field=ID) - Initial State Check:
wp post meta get $TARGET_ID [META_KEY_FOR_RATING](e.g.,_dr_recipe_ratingordelicious_recipes_rating_count).
7. Expected Results
- The
admin-ajax.phpresponse should be200 OKor a JSON success message (e.g.,{"success":true}). - The underlying data (post meta or user meta) should change despite the request being unauthenticated.
- No "403 Forbidden" or "Security check failed" errors should occur if the nonce is obtained correctly or missing.
8. Verification Steps
- Meta Check: Use WP-CLI to verify the change in the database.
wp post meta get $TARGET_ID [META_KEY_FOR_RATING] - Repeatability: Verify that the action can be performed multiple times from a "logged-out" state (no cookies in
http_request).
9. Alternative Approaches
- No-Nonce Bypass: If
check_ajax_refereris called withdie=false(e.g.,check_ajax_referer('...', '...', false)), attempt the request without a nonce. - User Meta Manipulation: If the vulnerability allows updating user settings, try targeting
update_user_metavia an action likedelicious_recipes_save_user_profileif it is incorrectly mapped tonopriv. - Settings Reset: Check if the plugin registers any "reset" or "import" actions to
nopriv, which would increase severity to CVSS 9.8+ (unlikely given CVSS 5.3, but worth a quick grep).
Grep Command for Initial Audit:
grep -rP "add_action\s*\(\s*['\"]wp_ajax_nopriv_" wp-content/plugins/delicious-recipes/
For each result, inspect the callback for:
current_user_can(Presence of this usually means it's safe).check_ajax_referer(Presence of this requires nonce extraction).
Summary
The WP Delicious plugin for WordPress (versions up to 1.9.5) fails to implement authorization and nonce validation on several AJAX handlers, specifically those registered via the nopriv_ hook. This allows unauthenticated attackers to perform actions such as artificially inflating recipe ratings or modifying like/dislike counts by sending crafted requests to the WordPress AJAX endpoint.
Vulnerable Code
// wp-content/plugins/delicious-recipes/includes/class-delicious-recipes-ajax.php add_action( 'wp_ajax_delicious_recipes_rating', array( $this, 'delicious_recipes_rating' ) ); add_action( 'wp_ajax_nopriv_delicious_recipes_rating', array( $this, 'delicious_recipes_rating' ) ); public function delicious_recipes_rating() { // Vulnerability: No check_ajax_referer() or current_user_can() verification $post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0; $rating = isset( $_POST['rating'] ) ? sanitize_text_field( $_POST['rating'] ) : ''; if ( $post_id ) { $this->update_recipe_rating( $post_id, $rating ); wp_send_json_success(); } wp_send_json_error(); }
Security Fix
@@ -10,6 +10,10 @@ public function delicious_recipes_rating() { + if ( ! check_ajax_referer( 'delicious-recipes-nonce', 'security', false ) ) { + wp_send_json_error( array( 'message' => __( 'Security check failed', 'delicious-recipes' ) ) ); + } + $post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0; $rating = isset( $_POST['rating'] ) ? sanitize_text_field( $_POST['rating'] ) : '';
Exploit Outline
1. Identify a target recipe post and its corresponding ID (post_id) on the WordPress site. 2. Access the recipe page as an unauthenticated user and inspect the HTML source to find the AJAX nonce, usually located within the 'delicious_recipes_params' or similar JavaScript object. 3. Construct an HTTP POST request to '/wp-admin/admin-ajax.php'. 4. Include the following parameters in the request body: 'action=delicious_recipes_rating', 'security=[NONCE]', 'post_id=[TARGET_ID]', and 'rating=[DESIRED_VALUE]'. 5. Submit the request; the server will process the rating update despite the lack of user authentication.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.