Cnvrse < 026.02.10.20 - Unauthenticated Insecure Direct Object Reference
Description
The Cnvrse plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and excluding, 026.02.10.20 due to missing validation on a user controlled key. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<026.02.10.20What Changed in the Fix
Changes introduced in v026.02.10.20
Source Code
WordPress.org SVNThis vulnerability is an **Insecure Direct Object Reference (IDOR)** in the Cnvrse plugin, specifically within its REST API implementation. The plugin fails to validate whether the requester has the authority to interact with a specific "object" (likely a conversation or message) identified by a use…
Show full research plan
This vulnerability is an Insecure Direct Object Reference (IDOR) in the Cnvrse plugin, specifically within its REST API implementation. The plugin fails to validate whether the requester has the authority to interact with a specific "object" (likely a conversation or message) identified by a user-controlled key (ID).
Because the CVSS vector shows Integrity: Low and Confidentiality: None, the vulnerability likely allows an unauthenticated attacker to modify the state of a conversation (e.g., closing it, marking it as read, or changing its status) rather than reading private chat content.
1. Vulnerability Summary
- Vulnerability: IDOR (Insecure Direct Object Reference).
- Location: REST API endpoints registered by the plugin (likely within
src/orincludes/not provided in the snippet, typically under thecnvrse/v1namespace). - Cause: The
permission_callbackfor a sensitive REST route either returnstrue(allowing unauthenticated access) or fails to verify that the provided conversation/visitor ID belongs to the current session. - Impact: Unauthenticated attackers can manipulate the status of any active chat conversation by guessing or iterating through IDs.
2. Attack Vector Analysis
- Endpoint: A REST API route, likely
POST /wp-json/cnvrse/v1/conversations/(?P<id>\d+)/statusorPOST /wp-json/cnvrse/v1/conversation/update. - Parameter: A user-controlled "key" or "id" representing a conversation record.
- Authentication: None required (Unauthenticated).
- Precondition: At least one active conversation must exist in the system for the attacker to target.
3. Code Flow (Inferred)
- Route Registration: The plugin calls
register_rest_route( 'cnvrse/v1', '/conversation/(?P<id>\d+)', ... ). - Missing Authorization: The
permission_callbackis set to__return_trueto allow the chat widget (public visitors) to use it. - Missing Ownership Check: In the controller method (e.g.,
update_conversation), the code retrieves the conversation object using theidfrom the request:$conversation = get_post( $request['id'] );. - Unauthorized Action: The code proceeds to update the post status or metadata without checking if the visitor's session cookie or a secret "visitor key" matches the owner of that conversation.
4. Nonce Acquisition Strategy
REST API endpoints in WordPress usually require a _wpnonce (for the wp_rest action) if the user is authenticated. For unauthenticated "public" endpoints, a nonce is often required to prevent CSRF.
- Identify Script: The plugin likely enqueues a script for the chat widget. Search for
wp_localize_scriptin the codebase. - Create Trigger Page: Create a page where the chat widget is active.
wp post create --post_type=page --post_status=publish --post_title="Chat Page" --post_content="Contact us!" - Extract Nonce:
Navigate to the page and usebrowser_evalto find the localization object.- Candidate Variable:
window.cnvrseSettingsorwindow.cnvrse_data. - Command:
browser_eval("window.cnvrseSettings?.nonce")orbrowser_eval("window.cnvrse_data?.rest_nonce").
- Candidate Variable:
5. Exploitation Strategy
Step 1: Discover the Target ID
Since conversations are stored as Custom Post Types (inferred from readme), they use sequential IDs. The attacker can target a known ID or iterate.
Step 2: Identify the REST Endpoint
Use grep to find the specific route:
grep -r "register_rest_route" .
Look for routes in the cnvrse/v1 namespace that handle "status", "close", or "update".
Step 3: Perform the IDOR Attack
Assuming the endpoint is /wp-json/cnvrse/v1/conversations/<id>/close:
- Request Method:
POST - URL:
http://vulnerable-test.local/wp-json/cnvrse/v1/conversations/123/close(where 123 is the target) - Headers:
Content-Type: application/json,X-WP-Nonce: <obtained_nonce> - Payload:
{ "status": "closed" }(if applicable)
Step 4: Use http_request (Example)
await http_request({
url: "http://localhost:8080/wp-json/cnvrse/v1/conversations/123",
method: "POST",
headers: {
"Content-Type": "application/json",
"X-WP-Nonce": "a1b2c3d4e5"
},
body: JSON.stringify({
"status": "closed"
})
});
6. Test Data Setup
- Activate Plugin: Ensure Cnvrse Lite is active.
- Simulate Victim: Open the site as a regular visitor and send a message through the chat widget. This creates a conversation record in the database.
- Identify Victim ID: Use WP-CLI to find the ID of the newly created conversation.
# Find the post type first wp post-type list # List posts of the chat type (e.g., cnvrse_conversation) wp post list --post_type=cnvrse_conversation
7. Expected Results
- The REST API returns a
200 OKor201 Createdresponse. - The response body confirms the status change (e.g.,
{"success": true}). - The attacker (who does not own conversation 123) successfully changed its state.
8. Verification Steps
After sending the exploit request, check the database state via WP-CLI:
# Check if the post status or a specific meta field changed
wp post get <ID> --field=post_status
# Or check meta if status is stored there
wp post meta list <ID>
9. Alternative Approaches
If the sequential ID is protected or validated, check for a "Visitor Key" IDOR:
- Many chat plugins use a UUID in a cookie (e.g.,
cnvrse_visitor_id). - Check if the API accepts this key as a parameter.
- Attempt to use your session's nonce but another visitor's UUID in the request body to see if the plugin validates the link between the session and the UUID.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.