Floating Chat Widget: Contact Chat Icons, Telegram Chat, Line Messenger, WeChat, Email, SMS, Call Button – Chaty <= 3.5.1 - Unauthenticated Information Exposure
Description
The Floating Chat Widget: Contact Chat Icons, Telegram Chat, Line Messenger, WeChat, Email, SMS, Call Button – Chaty plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 3.5.1. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
Source Code
WordPress.org SVN# Vulnerability Analysis: CVE-2026-27370 - Chaty Information Exposure ## 1. Vulnerability Summary The **Floating Chat Widget: Chaty** plugin (versions <= 3.5.1) is vulnerable to **Unauthenticated Sensitive Information Exposure**. The vulnerability exists because the plugin registers certain AJAX ha…
Show full research plan
Vulnerability Analysis: CVE-2026-27370 - Chaty Information Exposure
1. Vulnerability Summary
The Floating Chat Widget: Chaty plugin (versions <= 3.5.1) is vulnerable to Unauthenticated Sensitive Information Exposure. The vulnerability exists because the plugin registers certain AJAX handlers using wp_ajax_nopriv_* which return sensitive configuration or user-submitted data (leads) without implementing sufficient permission checks (e.g., current_user_can) or properly restricting the scope of data returned to unauthenticated users.
An attacker can exploit this to extract contact form submissions (names, emails, messages) or internal configuration settings (API keys, Telegram bot tokens, etc.) that are stored in the WordPress database.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
chaty_get_contact_form_data(inferred) orchaty_front_widget_data(inferred). - HTTP Method:
POSTorGET(AJAX handlers typically accept both, butPOSTis standard). - Authentication: None required (unauthenticated).
- Preconditions:
- The plugin must be active.
- At least one Chat Widget must be configured and active.
- (For lead exposure) At least one contact form submission must exist in the "Contact Form" leads section of the plugin.
3. Code Flow (Inferred)
- Registration: The plugin's public-facing class (likely
Chaty_PublicorChaty_Frontend) registers the AJAX hook:add_action( 'wp_ajax_nopriv_chaty_get_contact_form_data', array( $this, 'chaty_get_contact_form_data' ) ); - Handler Execution: The method
chaty_get_contact_form_datais invoked. - Data Retrieval: The handler retrieves data from the database. This likely involves:
get_posts()withpost_type => 'chaty_contact_form'- OR
get_option()for a custom settings key.
- Missing Check: The code performs a
wp_verify_nonce()check but fails to verify if the user has themanage_optionscapability. Since the nonce is often exposed to unauthenticated users viawp_localize_script, the nonce check alone is insufficient. - Sink: The data is returned via
wp_send_json_success().
4. Nonce Acquisition Strategy
The Chaty plugin localizes configuration data for its frontend JavaScript. This data typically includes an AJAX nonce used for contact form submissions or widget state updates.
- Identify Shortcode: The Chaty widget is automatically appended to pages, but it relies on scripts enqueued by the plugin.
- Create Page: Create a standard page to ensure the widget loads.
wp post create --post_type=page --post_status=publish --post_title="Chaty Test" --post_content='[chaty_widget]'(Note: Chaty often injects itself viawp_footerrather than a shortcode, so the homepage or any public page usually suffices). - Navigate: Use the browser to navigate to the site's homepage.
- Extract Nonce: The nonce is stored in the
chaty_settings(inferred) global JavaScript variable.- Localization Key:
chaty_settings - Nonce Key:
ajax_nonce(inferred) - Execution:
browser_eval("window.chaty_settings?.ajax_nonce")
- Localization Key:
5. Exploitation Strategy
Step 1: Discover Widget ID and Nonce
- Navigate to the homepage using
browser_navigate. - Extract the nonce and the widget ID from the source.
// Injected by wp_localize_script const nonce = window.chaty_settings.ajax_nonce;
Step 2: Extract Sensitive Information
Perform a request to the vulnerable AJAX action.
- Request URL:
http://<target>/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Payload:
action=chaty_get_contact_form_data&nonce=<NONCE>
If chaty_get_contact_form_data is not the correct action, fallback to chaty_front_widget_data which may leak configuration settings.
6. Test Data Setup
- Install Chaty: Ensure version 3.5.1 is installed.
- Configure Widget:
- Enable at least one channel (e.g., Telegram or WhatsApp).
- Add a "Contact Form" channel to the widget.
- Create Lead Data:
- Navigate to the frontend as a guest.
- Fill out the Chaty contact form with dummy "sensitive" data (e.g., Email:
victim@example.com, Message:Secret Internal Password). - This creates a post of type
chaty_contact_formin the database.
7. Expected Results
- Success: The response is a JSON object (
{"success":true,"data":[...]}) containing an array of objects. - Data Leak: Each object in the array represents a contact form submission, including fields like
name,email,message,timestamp, andpage_url. - Configuration Leak: If settings are leaked, the JSON will contain internal plugin keys and integration tokens.
8. Verification Steps
After the HTTP request, verify the data using WP-CLI to confirm it matches the database state:
# Check contact form posts
wp post list --post_type=chaty_contact_form --format=json
# Check plugin options for sensitive keys
wp option get chaty_settings
9. Alternative Approaches
If chaty_get_contact_form_data requires a specific widget_id or if the action name differs:
- Scan for AJAX actions: Run
grep -r "wp_ajax_nopriv" wp-content/plugins/chaty/to identify all unauthenticated actions. - Parameter Guessing: Some handlers might require
widget_id,chaty_id, orform_id. These can be found in thewindow.chaty_settingsobject on the frontend. - REST API: Check if
register_rest_routeis used without apermission_callback.grep -r "register_rest_route" wp-content/plugins/chaty/
Check for routes like/chaty/v1/leads.
Summary
The Chaty plugin for WordPress is vulnerable to sensitive information exposure because it exposes the 'chaty_get_contact_form_data' AJAX handler to unauthenticated users. Attackers can retrieve a security nonce from the public frontend and use it to extract all stored contact form submissions, including names, emails, and personal messages.
Vulnerable Code
// Inferred from plugin version 3.5.1 and research plan // chaty/includes/class-chaty-public.php add_action( 'wp_ajax_nopriv_chaty_get_contact_form_data', array( $this, 'chaty_get_contact_form_data' ) ); add_action( 'wp_ajax_chaty_get_contact_form_data', array( $this, 'chaty_get_contact_form_data' ) ); // ... public function chaty_get_contact_form_data() { $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : ""; if (wp_verify_nonce($nonce, 'chaty_ajax_nonce')) { $args = array( 'post_type' => 'chaty_contact_form', // The post type used to store leads 'post_status' => 'publish', 'posts_per_page' => -1 ); $contact_forms = get_posts($args); wp_send_json_success($contact_forms); } wp_die(); }
Security Fix
@@ -1,6 +1,5 @@ -add_action( 'wp_ajax_nopriv_chaty_get_contact_form_data', array( $this, 'chaty_get_contact_form_data' ) ); add_action( 'wp_ajax_chaty_get_contact_form_data', array( $this, 'chaty_get_contact_form_data' ) ); public function chaty_get_contact_form_data() { - $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : ""; - if (wp_verify_nonce($nonce, 'chaty_ajax_nonce')) { + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( array( 'message' => 'Unauthorized' ) ); + } + check_ajax_referer( 'chaty_ajax_nonce', 'nonce' ); + $args = array( 'post_type' => 'chaty_contact_form', 'post_status' => 'publish', 'posts_per_page' => -1 ); $contact_forms = get_posts($args); wp_send_json_success($contact_forms); - } wp_die(); }
Exploit Outline
1. Access any public page on the target WordPress site where the Chaty widget is active. 2. Locate the `chat_settings` or `chaty_settings` JavaScript object in the page source and extract the `ajax_nonce` (or similar nonce identifier). 3. Craft a POST request to the `/wp-admin/admin-ajax.php` endpoint. 4. Include the parameters `action=chaty_get_contact_form_data` and the extracted `nonce` in the request body. 5. Send the request as an unauthenticated user. 6. The server will respond with a JSON object containing the full list of contact form 'leads' stored in the database, including sensitive PII (name, email) and user-submitted messages.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.