[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fv861Ft0ocGrPyF-fCQbJd8t4ibeRxiBHfsr4MQVnBIs":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":28,"research_verified":29,"research_rounds_completed":30,"research_plan":31,"research_summary":32,"research_vulnerable_code":33,"research_fix_diff":34,"research_exploit_outline":35,"research_model_used":36,"research_started_at":37,"research_completed_at":38,"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":29,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":29,"source_links":39},"CVE-2026-31917","erp-authenticated-crm-agent-sql-injection","ERP \u003C= 1.16.10 - Authenticated (Crm agent+) SQL Injection","The ERP plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.16.10 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 crm agent-level access and above, to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.","erp",null,"\u003C=1.16.10","1.16.11","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-02-05 00:00:00","2026-04-15 20:58:32",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F9b5618b1-99fe-422a-9485-d51342e178b3?source=api-prod",70,[22,23,24,25,26,27],"includes\u002FAPI\u002FAnnouncementsController.php","includes\u002Ffunctions-people.php","modules\u002Fcrm\u002Fincludes\u002FCLI\u002FCommands.php","modules\u002Fhrm\u002Fincludes\u002FAPI\u002FAnnouncementsController.php","modules\u002Fhrm\u002Fincludes\u002FAPI\u002FEmployeesController.php","modules\u002Fhrm\u002Fincludes\u002FCLI\u002FCommands.php","researched",false,3,"This research plan targets a SQL Injection vulnerability in the **ERP** plugin (Complete HR, Accounting & CRM Suite) affecting version **1.16.10** and below.\n\n### 1. Vulnerability Summary\nThe vulnerability exists in the `erp_get_peoples()` function within `includes\u002Ffunctions-people.php`. This function is the core utility for retrieving \"peoples\" (contacts, customers, employees, vendors) across all ERP modules. The function fails to use `$wpdb->prepare()` or adequate escaping when processing the `meta_query` argument, allowing an attacker to inject arbitrary SQL into the `WHERE` clause.\n\n### 2. Attack Vector Analysis\n*   **Vulnerable Endpoint**: The WordPress REST API. Specifically, endpoints that call `erp_get_peoples()`. The most likely target is the CRM contacts listing: `GET \u002Fwp-json\u002Ferp\u002Fv1\u002Fcrm\u002Fcontacts`.\n*   **Vulnerable Parameter**: `meta_query`. Specifically the sub-parameters `meta_key` or `meta_value`.\n*   **Authentication Level**: Authenticated users with **CRM Agent** permissions (`crm_agent` role) or higher.\n*   **Vulnerability Type**: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection').\n*   **Preconditions**: The CRM module must be active (which is the default for this plugin).\n\n### 3. Code Flow\n1.  **Entry Point**: A REST API request is made to `\u002Fwp-json\u002Ferp\u002Fv1\u002Fcrm\u002Fcontacts`.\n2.  **Controller**: The request is handled by a controller (likely `WeDevs\\ERP\\CRM\\API\\ContactsController`) which extracts query parameters and passes them to a data-fetching function.\n3.  **Data Fetcher**: The controller calls `erp_crm_get_contacts()` or directly calls `erp_get_peoples()` in `includes\u002Ffunctions-people.php`.\n4.  **Vulnerable Sink**: `erp_get_peoples()` (Line 96 in `includes\u002Ffunctions-people.php`):\n    ```php\n    if ( $meta_query ) {\n        $sql['join'][] = \"LEFT JOIN $pepmeta_tb as people_meta on people.id = people_meta.`erp_people_id`\";\n\n        $meta_key   = isset( $meta_query['meta_key'] ) ? $meta_query['meta_key'] : '';\n        $meta_value = isset( $meta_query['meta_value'] ) ? $meta_query['meta_value'] : '';\n        $compare    = isset( $meta_query['compare'] ) ? $meta_query['compare'] : '=';\n\n        \u002F\u002F INJECTION POINT: $meta_key and $meta_value are concatenated directly\n        $sql['where'][] = \"AND people_meta.meta_key='$meta_key' and people_meta.meta_value='$meta_value'\";\n    }\n    ```\n5.  **Execution**: The `$sql['where']` array is imploded and appended to the final query string, which is then executed via `$wpdb->get_results()` without preparation (Line 228).\n\n### 4. Nonce Acquisition Strategy\nREST API exploitation requires a `wp_rest` nonce sent in the `X-WP-Nonce` header.\n\n1.  **Navigate to Dashboard**: Login as a CRM Agent and navigate to `\u002Fwp-admin\u002Fadmin.php?page=erp-crm`.\n2.  **Extract Nonce**: The ERP plugin localizes several scripts. Use `browser_eval` to find the nonce in the `wpErp` or similar global objects.\n    *   **Potential Variable**: `window.wpErp?.nonce` or `window.wpCRM?.nonce`.\n    *   **Fallback**: Standard WordPress REST nonce: `browser_eval(\"wpApiSettings.nonce\")`.\n\n### 5. Exploitation Strategy\nWe will perform a **Time-Based Blind SQL Injection** to verify the vulnerability.\n\n1.  **Setup CRM Agent**: Ensure a user exists with the `crm_agent` role.\n2.  **Baseline Request**: Perform a normal GET request to the contacts endpoint to ensure it returns a 200 OK.\n    *   `GET \u002Fwp-json\u002Ferp\u002Fv1\u002Fcrm\u002Fcontacts`\n3.  **Payload Construction**: Inject a `SLEEP()` command via the `meta_query[meta_key]` parameter.\n    *   **Payload**: `any' OR (SELECT 1 FROM (SELECT SLEEP(5))x) -- -`\n    *   **Full URL**: `\u002Fwp-json\u002Ferp\u002Fv1\u002Fcrm\u002Fcontacts?meta_query[meta_key]=any%27%20OR%20(SELECT%201%20FROM%20(SELECT%20SLEEP(5))x)%20--%20-&meta_query[meta_value]=1`\n4.  **Execute Request**: Use `http_request` with the `X-WP-Nonce` header.\n5.  **Observe Response Time**: If the response takes ~5 seconds, the injection is successful.\n\n### 6. Test Data Setup\n1.  **Activate Plugin**: Ensure `erp` is active.\n2.  **Activate CRM**: Ensure the CRM module is enabled via ERP settings.\n3.  **Create User**:\n    ```bash\n    wp user create attacker attacker@example.com --role=erp_crm_agent --user_pass=password\n    ```\n4.  **Create Sample Contact**: The query needs at least one contact to process logic in some versions.\n    ```bash\n    # Use WP-CLI to create a contact if possible, or navigate via browser to create one.\n    ```\n\n### 7. Expected Results\n*   **Baseline**: Response time \u003C 500ms.\n*   **Exploit**: Response time > 5000ms.\n*   **HTTP Status**: 200 OK (the injection is in the `WHERE` clause of a `SELECT` query, so it typically returns an empty set or a list of contacts).\n\n### 8. Verification Steps\nAfter the HTTP exploit, verify the lack of preparation in the source code:\n1.  **Check for Prepare**: `grep -A 15 \"if ( \\$meta_query )\" includes\u002Ffunctions-people.php`\n2.  **Confirm Sink**: Verify that `$wpdb->get_results` is called on the `$final_query` variable without a `prepare()` wrapper in the same file.\n\n### 9. Alternative Approaches\nIf `meta_query` is not directly exposed via the REST API, test the `orderby` parameter in the same function:\n*   **Vulnerable Line**: `$sql_order_by = \"ORDER BY $orderby $order\";` (Line 90).\n*   **Payload**: `?orderby=(SELECT 1 FROM (SELECT SLEEP(5))x)`\n\nIf `\u002Ferp\u002Fv1\u002Fcrm\u002Fcontacts` is not the correct route, check for:\n*   `\u002Fwp-json\u002Ferp\u002Fv1\u002Fhrm\u002Femployees` (Requires `erp_view_list` capability).\n*   `\u002Fwp-json\u002Ferp\u002Fv1\u002Faccounting\u002Fv1\u002Fcustomers` (Requires accounting access).\nAny endpoint calling `erp_get_peoples()` will be vulnerable.","The ERP plugin for WordPress is vulnerable to SQL Injection via the erp_get_peoples() function due to a lack of parameter preparation and whitelisting. Authenticated attackers with CRM agent permissions can inject arbitrary SQL commands through parameters like meta_query or orderby via REST API endpoints, allowing for sensitive data extraction from the database.","\u002F\u002F includes\u002Ffunctions-people.php line 90\n$sql_order_by = \"ORDER BY $orderby $order\";\n\n\u002F\u002F ---\n\n\u002F\u002F includes\u002Ffunctions-people.php line 96\nif ( $meta_query ) {\n    $sql['join'][] = \"LEFT JOIN $pepmeta_tb as people_meta on people.id = people_meta.`erp_people_id`\";\n\n    $meta_key   = isset( $meta_query['meta_key'] ) ? $meta_query['meta_key'] : '';\n    $meta_value = isset( $meta_query['meta_value'] ) ? $meta_query['meta_value'] : '';\n    $compare    = isset( $meta_query['compare'] ) ? $meta_query['compare'] : '=';\n\n    \u002F\u002F INJECTION POINT: $meta_key and $meta_value are concatenated directly\n    $sql['where'][] = \"AND people_meta.meta_key='$meta_key' and people_meta.meta_value='$meta_value'\";\n}","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ferp\u002F1.16.10\u002Fincludes\u002Ffunctions-people.php\t2026-01-01 17:26:14.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Ferp\u002F1.16.11\u002Fincludes\u002Ffunctions-people.php\t2026-02-09 12:22:10.000000000 +0000\n@@ -61,6 +61,44 @@\n     if ( false === $items ) {\n         extract( $args );\n \n+        \u002F\u002F Whitelist allowed orderby columns to prevent SQL injection\n+        $allowed_orderby = [\n+            'id',\n+            'user_id',\n+            'first_name',\n+            'last_name',\n+            'company',\n+            'email',\n+            'phone',\n+            'mobile',\n+            'other',\n+            'website',\n+            'fax',\n+            'notes',\n+            'street_1',\n+            'street_2',\n+            'city',\n+            'state',\n+            'postal_code',\n+            'country',\n+            'currency',\n+            'life_stage',\n+            'contact_owner',\n+            'hash',\n+            'created_by',\n+            'created',\n+        ];\n+\n+        if ( ! in_array( $orderby, $allowed_orderby, true ) ) {\n+            $orderby = 'id';\n+        }\n+\n+        \u002F\u002F Whitelist allowed order directions to prevent SQL injection\n+        $order = strtoupper( $order );\n+        if ( ! in_array( $order, [ 'ASC', 'DESC' ], true ) ) {\n+            $order = 'DESC';\n+        }\n+\n         $sql         = [];\n         $trashed_sql = $trashed ? '`deleted_at` is not null' : '`deleted_at` is null';","The exploit targets the erp_get_peoples() function, which is utilized by several REST API routes. An attacker needs an account with at least 'crm_agent' permissions. \n\n1. Authenticate as a CRM Agent and retrieve a REST API nonce (X-WP-Nonce) from the WordPress dashboard (often located in the wpErp or wpApiSettings JavaScript globals).\n2. Send a GET request to a vulnerable REST route, such as `\u002Fwp-json\u002Ferp\u002Fv1\u002Fcrm\u002Fcontacts`.\n3. Include a payload in the `meta_query[meta_key]` or `orderby` parameters. For example, setting `meta_query[meta_key]` to `any' OR (SELECT 1 FROM (SELECT SLEEP(5))x) -- -` triggers a time-based blind SQL injection.\n4. Observe the response latency; a significant delay (e.g., 5 seconds) confirms the vulnerability and successful execution of the injected SQL.","gemini-3-flash-preview","2026-04-21 04:12:41","2026-04-21 04:13:49",{"type":40,"vulnerable_version":41,"fixed_version":11,"vulnerable_browse":42,"vulnerable_zip":43,"fixed_browse":44,"fixed_zip":45,"all_tags":46},"plugin","1.16.10","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ferp\u002Ftags\u002F1.16.10","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ferp.1.16.10.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ferp\u002Ftags\u002F1.16.11","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Ferp.1.16.11.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Ferp\u002Ftags"]