Contest Gallery – Upload & Vote Photos, Media, Sell with PayPal & Stripe <= 28.1.7 - Missing Authorization
Description
The Contest Gallery – Upload & Vote Photos, Media, Sell with PayPal & Stripe plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 28.1.7. 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
<=28.1.7What Changed in the Fix
Changes introduced in v29.0.0
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-42657 ## Vulnerability Summary The **Contest Gallery** plugin for WordPress is vulnerable to **Missing Authorization** in its AJAX handlers. Specifically, the function `post_cg_set_frontend_cookie` in `ajax/ajax-functions-frontend.php` is registered for unaut…
Show full research plan
Exploitation Research Plan - CVE-2026-42657
Vulnerability Summary
The Contest Gallery plugin for WordPress is vulnerable to Missing Authorization in its AJAX handlers. Specifically, the function post_cg_set_frontend_cookie in ajax/ajax-functions-frontend.php is registered for unauthenticated users via wp_ajax_nopriv_post_cg_set_frontend_cookie but lacks any nonce verification or capability checks. This allows an unauthenticated attacker to set sensitive session cookies (cg_order, contest-gal1ery-{ID}-voting, contest-gal1ery-{ID}-upload) that are used by the plugin to authorize access to orders, voting capabilities, and upload permissions.
Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
post_cg_set_frontend_cookie - Authentication: Unauthenticated (via
wp_ajax_nopriv_) - Parameters:
gid: The Gallery ID (numeric).cgIsUpload: (Optional) If set, triggers the creation of the upload authorization cookie.cgOrderIdHash: (Optional) If set, triggers the creation of thecg_ordercookie (used for order access).
- Preconditions: The attacker needs to know a valid Gallery ID (easily found by viewing the site) or an Order ID hash.
Code Flow
1
Summary
The Contest Gallery plugin for WordPress fails to implement authorization checks or nonce verification on the `post_cg_set_frontend_cookie` AJAX function. This allows unauthenticated attackers to programmatically set session cookies that grant unauthorized access to restricted features such as photo uploading, voting, and private order details.
Vulnerable Code
// ajax/ajax-functions-frontend.php line 105 add_action('wp_ajax_nopriv_post_cg_set_frontend_cookie', 'post_cg_set_frontend_cookie'); add_action('wp_ajax_post_cg_set_frontend_cookie', 'post_cg_set_frontend_cookie'); if (!function_exists('post_cg_set_frontend_cookie')) { function post_cg_set_frontend_cookie() { global $wpdb; if (defined('DOING_AJAX') && DOING_AJAX) { if(!empty($_REQUEST['gid'])){ $galeryID = intval(sanitize_text_field($_REQUEST['gid']));// is gidReal } if(!empty($_POST['cgIsUpload'])){ if(!isset($_COOKIE['contest-gal1ery-'.$galeryID.'-upload'])) { cg_set_cookie($galeryID,'upload'); // thats it cookie is set... after that cookie is available in browser } }elseif(!empty($_POST['cgOrderIdHash'])){ setcookie('cg_order', cg_hash_function('---cg_order---'.sanitize_text_field($_POST['cgOrderIdHash'])), time() + ( 7 * 24 * 60 * 60), "/"); }else{ if(!isset($_COOKIE['contest-gal1ery-'.$galeryID.'-voting'])) { cg_set_cookie($galeryID,'voting'); // thats it cookie is set... after that cookie is available in browser } } exit(); } else { exit(); } } }
Security Fix
@@ -1,10 +1,60 @@ <?php +if (!function_exists('cg_backend_ajax_error_json')) { + function cg_backend_ajax_error_json($message, $status = 400, $code = 'cg_backend_ajax_error') { + wp_send_json_error(array( + 'message' => $message, + 'code' => $code + ), $status); + } +} + +if (!function_exists('cg_backend_ajax_require_access_json')) { + function cg_backend_ajax_require_access_json() { + if (!defined('DOING_AJAX') || !DOING_AJAX) { + cg_backend_ajax_error_json('Invalid AJAX request.', 400, 'cg_invalid_ajax_request'); + } + + if (!is_user_logged_in() || !cg_user_has_backend_access()) { + cg_backend_ajax_error_json('This area can be edited only as administrator, editor or author.', 403, 'cg_missing_rights'); + } + + $cg_nonce = ''; + if (isset($_POST['cg_nonce'])) { + $cg_nonce = sanitize_text_field($_POST['cg_nonce']); + } elseif (isset($_GET['cg_nonce'])) { + $cg_nonce = sanitize_text_field($_GET['cg_nonce']); + } + + if (empty($cg_nonce) || !wp_verify_nonce($cg_nonce, 'cg_nonce')) { + wp_send_json_error(array( + 'message' => 'WP nonce security token not set or not valid anymore.', + 'code' => 'cg_nonce_invalid', + 'version' => cg_get_version() + ), 403); + } + } +} + +if (!function_exists('cg_backend_ajax_validate_gallery_hash_json')) { + function cg_backend_ajax_validate_gallery_hash_json($GalleryID, $galleryHash) { + $GalleryID = absint($GalleryID); + if (empty($GalleryID) || empty($galleryHash)) { + cg_backend_ajax_error_json('Missing gallery validation data.', 403, 'cg_missing_gallery_hash'); + } + + $galleryHashToCompare = md5(wp_salt('auth') . '---cngl1---' . $GalleryID); + if ($galleryHash !== $galleryHashToCompare) { + cg_backend_ajax_error_json('Invalid gallery validation data.', 403, 'cg_invalid_gallery_hash'); + } + } +} + // post_cg_get_current_permalinks add_action('wp_ajax_post_cg_get_current_permalinks', 'post_cg_get_current_permalinks'); if (!function_exists('post_cg_get_current_permalinks')) { function post_cg_get_current_permalinks() { - cg_check_nonce(); + cg_require_backend_access(); global $wpdb; $tablename = $wpdb->prefix . "contest_gal1ery";
Exploit Outline
The exploit targets the `/wp-admin/admin-ajax.php` endpoint using the `post_cg_set_frontend_cookie` action. An unauthenticated attacker sends a POST request with the `gid` parameter set to a target Gallery ID. To gain upload permissions, they include the `cgIsUpload` parameter. To gain access to a specific order, they include the `cgOrderIdHash` parameter. The server responds by setting the corresponding session cookies (`contest-gal1ery-{ID}-upload` or `cg_order`) in the attacker's browser without verifying if the attacker is authorized to perform these actions or providing a valid nonce.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.