[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fpATst22B_Uv5WyBunNZqBPfXc-HXyaN3VPbhHsxpZH8":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":24,"research_verified":25,"research_rounds_completed":20,"research_plan":26,"research_summary":27,"research_vulnerable_code":28,"research_fix_diff":29,"research_exploit_outline":30,"research_model_used":31,"research_started_at":32,"research_completed_at":33,"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":25,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":25,"source_links":34},"CVE-2026-42732","quads-ads-manager-for-google-adsense-missing-authorization-2","Quads Ads Manager for Google AdSense \u003C= 3.0.2 - Missing Authorization","The Quads Ads Manager for Google AdSense plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 3.0.2. This makes it possible for unauthenticated attackers to perform an unauthorized action.","quick-adsense-reloaded",null,"\u003C=3.0.2","3.0.3","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-05-24 00:00:00","2026-05-26 19:43:24",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Ffa5f1c1b-fb20-4106-a9d3-6e4e304d30be?source=api-prod",3,[22,23],"changelog.txt","includes\u002Fad-selling-helper.php","researched",false,"# Exploitation Research Plan - CVE-2026-42732\n\n## 1. Vulnerability Summary\nThe **Quads Ads Manager for Google AdSense** plugin (up to version 3.0.2) contains a **Missing Authorization** vulnerability in its ad-selling module. Specifically, the function `quads_authorize_payment_success` is hooked to WordPress's `init` action, making it accessible on every page load. The function lacks proper authorization checks (e.g., `current_user_can`) and fails to verify if the request originated from a legitimate payment gateway. While it contains a check for `is_user_logged_in()` and a nonce check in the provided source, the CVE identifies it as unauthenticated, suggesting either these checks are bypassable, were absent in earlier versions, or the nonce itself is exposed to unauthenticated users.\n\nSuccessful exploitation allows an attacker to mark pending ad orders as \"paid\" without actual payment, effectively stealing advertising space.\n\n## 2. Attack Vector Analysis\n- **Endpoint**: Any WordPress URL (via the `init` hook).\n- **Vulnerable Function**: `quads_authorize_payment_success()` in `includes\u002Fad-selling-helper.php`.\n- **HTTP Method**: `GET`.\n- **Payload Parameters**:\n    - `status`: Must be exactly `success`.\n    - `ad_slot_id`: An integer representing the target ad slot ID.\n    - `refId`: An integer representing the order ID (intended to be mapped to `$order_id`).\n    - `user_id`: An integer representing the user ID of the ad buyer.\n    - `security`: A WordPress nonce for the action `'security'`.\n- **Preconditions**: \n    - The \"Sellable Ads\" feature must be active.\n    - A pending order must exist in the `wp_quads_adbuy_data` table.\n    - A valid nonce for the `'security'` action must be obtained.\n\n## 3. Code Flow\n1. **Entry Point**: A `GET` request is made to any WordPress page.\n2. **Hook**: The `init` hook triggers `quads_authorize_payment_success` in `includes\u002Fad-selling-helper.php`.\n3. **Authentication Check**: The function checks `is_user_logged_in()`. (If the CVE is unauthenticated, this check might be absent in vulnerable versions or the attacker simply needs a Subscriber account).\n4. **Nonce Verification**: `wp_verify_nonce( $_GET['security'], 'security' )`.\n5. **Logic Path**: If `status == 'success'`, `ad_slot_id > 0`, `refId != \"\"`, and `user_id > 0`, the code enters the update block.\n6. **Sink**: The plugin performs a database update:\n   ```php\n   $wpdb->update(\n       $table_name,\n       array('payment_status' => 'paid' , 'payment_response'=> wp_json_encode($params)),\n       array('id' => $order_id , 'user_id'=>$user->ID) \n   );\n   ```\n   *Note: In the provided source, `$order_id` and `$user_id` are used but not explicitly initialized from `$_GET` before the `absint()` call. This is likely a developer error in the plugin's code that may rely on `register_globals` (unlikely) or an earlier `extract($_GET)` (possible).*\n\n## 4. Nonce Acquisition Strategy\nThe nonce is tied to the action `'security'`. In this plugin, this generic nonce is typically localized for the frontend ad-buying form.\n\n1. **Identify Page**: The plugin creates a page with the slug `buy-adspace` containing the shortcode `[quads_buy_form]`.\n2. **Navigate**: Use the browser to navigate to `\u002Fbuy-adspace\u002F`.\n3. **Extract**: Use `browser_eval` to find the localized JavaScript object. The plugin usually localizes variables under a name related to \"quads\".\n   - **Candidate Variable**: `quads_ajax_object` or `quads_vars`.\n   - **Command**: `browser_eval(\"window.quads_ajax_object?.security\")` or `browser_eval(\"window.quads_vars?.security\")`.\n   - **Verification**: If no specific variable is found, search the HTML source for `\"security\":\"`.\n\n## 5. Exploitation Strategy\n1. **Setup Phase**:\n    - Ensure the plugin is active and the `wp_quads_adbuy_data` table exists.\n    - Create a \"Sellable Ad\" order in the database with `payment_status = 'pending'`.\n2. **Nonce Extraction**:\n    - Access the `\u002Fbuy-adspace\u002F` page and extract the `'security'` nonce.\n3. **Exploit Execution**:\n    - Construct the malicious GET request.\n    - **URL**: `http:\u002F\u002Flocalhost:8080\u002F?status=success&ad_slot_id=[SLOT_ID]&refId=[ORDER_ID]&user_id=[USER_ID]&security=[NONCE]`\n    - **Note**: If the source code in the target environment matches the provided snippet exactly, the undefined `$order_id` may cause the exploit to fail unless the agent can determine if the plugin uses `refId` as the order ID.\n4. **Confirmation**:\n    - Verify that the database record's `payment_status` has changed to `paid`.\n\n## 6. Test Data Setup\n```bash\n# 1. Create a test ad slot (if applicable) or identify an existing one\n# 2. Create the Buy Adspace page if it doesn't exist\nwp post create --post_type=page --post_title=\"Buy Adspace\" --post_status=publish --post_content='[quads_buy_form]' --post_name='buy-adspace'\n\n# 3. Create a pending order in the custom table (requires identifying the table name)\n# Assuming table: wp_quads_adbuy_data\n# Columns: id, user_id, ad_id, payment_status, etc.\nwp db query \"INSERT INTO wp_quads_adbuy_data (user_id, ad_id, payment_status, start_date, end_date) VALUES (1, 123, 'pending', '2025-01-01', '2025-01-31');\"\n# Note the ID of the inserted row for refId\n```\n\n## 7. Expected Results\n- The HTTP request should return a `200 OK` (the function returns nothing or calls `wp_mail`).\n- An email will be sent to the admin and user (can be checked via `wp mail list` if a mail catcher is used).\n- The database entry in `wp_quads_adbuy_data` for the specific `id` will have `payment_status` set to `'paid'`.\n\n## 8. Verification Steps\n```bash\n# Check the database for the status change\nwp db query \"SELECT id, payment_status FROM wp_quads_adbuy_data WHERE id = [ORDER_ID];\"\n\n# Verify the output matches 'paid'\n```\n\n## 9. Alternative Approaches\n- **Variable Context**: If the GET parameters `refId` and `user_id` do not populate the internal `$order_id` and `$user_id` variables, try adding them directly as `order_id=[ID]` and `user_id=[ID]` in the query string, as some plugins use `extract($_GET)` or `$_REQUEST`.\n- **Subscriber Level**: If the `is_user_logged_in()` check is strictly enforced, create a Subscriber user, log in, and then perform the request. The vulnerability is still \"Missing Authorization\" because a Subscriber should not be able to authorize payments for ad slots.","The Quads Ads Manager plugin for WordPress is vulnerable to unauthorized access via the quads_authorize_payment_success function. This function is hooked to 'init' and lacks proper authorization or capability checks, allowing authenticated attackers (like Subscribers) to mark pending ad orders as paid without completing actual payments.","\u002F\u002F includes\u002Fad-selling-helper.php\r\n\r\nadd_action( 'init', 'quads_authorize_payment_success' );\r\nfunction quads_authorize_payment_success(){\r\n    \r\n    if ( !is_user_logged_in() ) {\r\n        return false;\r\n    }\r\n    if( !isset( $_GET[ 'security' ] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET[ 'security' ] ) ), 'security' )){ \r\n        return false;\r\n    }\r\n    if( isset( $_GET['status'] ) && $_GET['status']=='success' && isset( $_GET['ad_slot_id'] ) && $_GET['ad_slot_id'] > 0 && isset( $_GET['refId'] ) && $_GET['refId'] != \"\" && isset( $_GET['user_id'] ) && intval( $_GET['user_id'] ) >0 && !isset( $_GET['target'] )){\r\n        $slot_id = absint( $_GET['ad_slot_id'] );\r\n        $order_id = absint($order_id);\r\n        $user_id = absint($user_id);\r\n        $price = get_post_meta( $slot_id, 'ad_cost' );\r\n\r\n---\r\n\r\n            $params = array();\r\n            $params['payment_date'] = gmdate('Y-m-d H:i:s');\r\n            \u002F\u002F phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching\r\n            $wpdb->update(\r\n                $table_name,\r\n                array('payment_status' => 'paid' , 'payment_response'=> wp_json_encode($params)), \u002F\u002F Data to update\r\n                array('id' => $order_id , 'user_id'=>$user->ID) \r\n            );","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fquick-adsense-reloaded\u002F3.0.2\u002Fincludes\u002Fad-selling-helper.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fquick-adsense-reloaded\u002F3.0.3\u002Fincludes\u002Fad-selling-helper.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fquick-adsense-reloaded\u002F3.0.2\u002Fincludes\u002Fad-selling-helper.php\t2026-04-16 14:19:34.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fquick-adsense-reloaded\u002F3.0.3\u002Fincludes\u002Fad-selling-helper.php\t2026-05-08 12:37:54.000000000 +0000\n@@ -1710,6 +1838,21 @@\n         }\n     }\n \n+    $price      = get_post_meta( $ad_slot_id, 'ad_cost', true );\n+    $currency   = 'USD';\n+    $days       = ( strtotime( $end_date ) - strtotime( $start_date ) ) \u002F ( 60 * 60 * 24 ) + 1;\n+    $total_cost = $price * $days;\n+    $name       = get_the_title( $ad_slot_id );\n+\n+    $coupon_parse = quads_parse_coupon_discount( $coupon_code, $ad_slot_id, (float) $total_cost );\n+    if ( 'invalid' === $coupon_parse['status'] || 'expired' === $coupon_parse['status'] ) {\n+        $err_msg = ( 'expired' === $coupon_parse['status'] )\n+            ? esc_html__( 'Coupon expired, please try another one.', 'quick-adsense-reloaded' )\n+            : esc_html__( 'Invalid coupon, please try another one.', 'quick-adsense-reloaded );\n+        wp_send_json_error( array( 'message' => $err_msg ) );\n+    }\n+    $total_cost = max( 0, (float) $total_cost - (float) $coupon_parse['discount'] );\n+\n     \u002F\u002F Insert the ad buy record in the database\n     global $wpdb;\n     $table_name = $wpdb->prefix . 'quads_adbuy_data';","1. Authentication: The attacker authenticates as a low-privileged user (e.g., Subscriber).\r\n2. Nonce Acquisition: The attacker visits the plugin's ad-selling page (typically \u002Fbuy-adspace\u002F) to extract a valid WordPress nonce for the action 'security'. This nonce is often localized in JavaScript variables like 'quads_ajax_object'.\r\n3. Order Identification: The attacker initiates an ad purchase or identifies an existing pending order ID (refId) and their own user_id.\r\n4. Request Construction: The attacker constructs a GET request to the site root with parameters mimicking a successful payment gateway callback: ?status=success&ad_slot_id=[SLOT_ID]&refId=[ORDER_ID]&user_id=[USER_ID]&security=[NONCE].\r\n5. Execution: Upon receiving the request, the init hook triggers quads_authorize_payment_success, which validates the nonce and user status but fails to verify that the user has administrative privileges or that the payment was verified by the provider. The plugin then updates the database to set the order status to 'paid'.","gemini-3-flash-preview","2026-06-04 21:34:35","2026-06-04 21:37:19",{"type":35,"vulnerable_version":36,"fixed_version":11,"vulnerable_browse":37,"vulnerable_zip":38,"fixed_browse":39,"fixed_zip":40,"all_tags":41},"plugin","3.0.2","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fquick-adsense-reloaded\u002Ftags\u002F3.0.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fquick-adsense-reloaded.3.0.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fquick-adsense-reloaded\u002Ftags\u002F3.0.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fquick-adsense-reloaded.3.0.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fquick-adsense-reloaded\u002Ftags"]