CVE-2026-32527

WP Insightly for Contact Form 7, WPForms, Elementor, Formidable and Ninja Forms <= 1.1.5 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
1.1.6
Patched in
8d
Time to patch

Description

The WP Insightly for Contact Form 7, WPForms, Elementor, Formidable and Ninja Forms 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.1.5. 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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.1.5
PublishedMarch 20, 2026
Last updatedMarch 27, 2026
Affected plugincf7-insightly

What Changed in the Fix

Changes introduced in v1.1.6

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on exploiting a **Missing Authorization** vulnerability in the **WP Insightly** plugin (version <= 1.1.5). The vulnerability allows authenticated users with Subscriber-level permissions to perform administrative actions, such as modifying plugin feeds or triggering CRM syn…

Show full research plan

This research plan focuses on exploiting a Missing Authorization vulnerability in the WP Insightly plugin (version <= 1.1.5). The vulnerability allows authenticated users with Subscriber-level permissions to perform administrative actions, such as modifying plugin feeds or triggering CRM synchronization, because the AJAX handlers fail to verify user capabilities.


1. Vulnerability Summary

  • Vulnerability: Missing Authorization (Insecure Direct Object Reference / Missing Capability Check).
  • Location: includes/plugin-pages.php within the vxcf_insightly_pages class.
  • Problem: The plugin registers multiple AJAX actions via wp_ajax_ hooks. While these hooks correctly restrict access to authenticated users, the callback functions (e.g., update_feed, send_to_crm, refresh_data) do not perform a current_user_can('manage_options') check.
  • Impact: A Subscriber can modify plugin configuration (Integrity) or trigger unauthorized data transmissions to Insightly CRM.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: update_feed_vxcf_insightly (inferred from $this->id = "vxcf_insightly" in cf7-insightly.php).
  • Authentication: Authenticated (Subscriber level or higher).
  • Payload: URL-encoded POST parameters including a nonce and feed configuration.
  • Preconditions:
    1. The plugin must be active.
    2. At least one "Feed" must exist in the plugin (to modify).
    3. The attacker must obtain a valid WordPress nonce (vx_nonce).

3. Code Flow

  1. Registration: In includes/plugin-pages.php, the __construct method registers AJAX handlers using the pattern wp_ajax_update_feed_vxcf_insightly.
  2. Trigger: A Subscriber sends a POST request to admin-ajax.php with action=update_feed_vxcf_insightly.
  3. Execution: WordPress routes the request to vxcf_insightly_pages::update_feed.
  4. Failure: The handler likely calls check_ajax_referer('vx_nonce', 'nonce') but fails to call current_user_can('manage_options'). The code proceeds to update the database table wp_vxcf_insightly_feeds based on $_POST data.

4. Nonce Acquisition Strategy

The nonce is generated using wp_create_nonce('vx_nonce'). In CRM Perks plugins, this nonce is typically exposed in the admin dashboard.

Strategy:

  1. The plugin often registers its submenus with the read capability (allowing Subscribers to see them) or leaks the nonce in the global admin script data.
  2. Access Test: Navigate to the plugin's main page as a Subscriber: /wp-admin/admin.php?page=vxcf_insightly.
  3. Extraction:
    • If the page loads, use browser_eval to extract the nonce from the hidden input field:
      document.getElementById('vx_nonce_field')?.value
    • Alternatively, check the global JS object (localized via wp_localize_script):
      window.vxcf_insightly_pages?.nonce (or similar, based on the $this->id).

5. Exploitation Strategy

We will demonstrate the vulnerability by modifying an existing feed's name using a Subscriber account.

Step 1: Obtain Nonce
Use the browser_navigate and browser_eval tools to grab the vx_nonce.

Step 2: Submit Malicious Update
Perform a POST request to admin-ajax.php.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=update_feed_vxcf_insightly&nonce=[NONCE]&feed_id=1&feed_name=VULNERABILITY_CONFIRMED&active=1
    
    (Note: Parameters based on standard CRM Perks feed update logic. If update_feed expects a serialized object, the feed parameter may be used instead.)

6. Test Data Setup

  1. Admin Action: Log in as Admin.
  2. Plugin Setup:
    • Go to "Insightly Feeds" and create one dummy feed named "Original Feed".
    • Note the id of the feed (usually 1 for the first feed).
  3. Subscriber Setup: Create a user attacker with the subscriber role.

7. Expected Results

  • The AJAX request should return a success message (likely JSON or a string like 1 or updated).
  • The Subscriber's request is accepted despite lacking administrative privileges.
  • The database record for the feed will be updated.

8. Verification Steps

  1. Database Check: Use WP-CLI to verify the feed name changed:
    wp db query "SELECT name FROM wp_vxcf_insightly_feeds WHERE id=1"
  2. UI Check: Log back in as Admin and view the Feeds list to see the altered name "VULNERABILITY_CONFIRMED".

9. Alternative Approaches

If update_feed is strictly protected, target refresh_data_vxcf_insightly:

  • Action: refresh_data_vxcf_insightly
  • Payload: action=refresh_data_vxcf_insightly&nonce=[NONCE]
  • Effect: Triggers an unauthorized API refresh/sync with Insightly.

If the Subscriber cannot access the plugin admin pages directly to get a nonce:

  • Check if the plugin enqueues its scripts on the Dashboard (index.php).
  • Try to find the nonce in the source of wp-admin/index.php.
  • If check_ajax_referer is used with die=false (common in some CRM Perks versions), try omitting the nonce entirely.
Research Findings
Static analysis — not yet PoC-verified

Summary

The WP Insightly plugin for WordPress fails to implement capability checks on several AJAX handlers, most notably the log detail viewer. This allows authenticated attackers, such as Subscribers, to access sensitive CRM logs, modify plugin settings, or trigger unauthorized data synchronization with the Insightly CRM.

Vulnerable Code

// includes/plugin-pages.php lines 19-30
public function __construct() {
  
  $this->data=$this->get_data_object();
global $pagenow;
  if(in_array($pagenow, array("admin-ajax.php"))){
  add_action('wp_ajax_update_feed_'.$this->id, array($this, 'update_feed'));
  add_action('wp_ajax_update_feed_sort_'.$this->id, array($this, 'update_feed_sort'));
  add_action('wp_ajax_get_field_map_'.$this->id, array($this, 'get_field_map_ajax'));
  add_action('wp_ajax_get_field_map_object_'.$this->id, array($this, 'get_field_map_object_ajax'));
  add_action('wp_ajax_get_objects_'.$this->id, array($this, 'get_objects_ajax'));
  add_action('wp_ajax_log_detail_'.$this->id, array($this, 'log_detail'));
   add_action('wp_ajax_refresh_data_'.$this->id, array($this, 'refresh_data')); 
  add_action('wp_ajax_send_to_crm_'.$this->id, array($this, 'send_to_crm')); 
  }

---

// includes/plugin-pages.php line 1416 (v1.1.5)
public function log_detail(){
$log_id=$this->post('id');
$log=$this->data->get_log_by_id($log_id); 
  $data=json_decode($log['data'],true);

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/cf7-insightly/1.1.5/cf7-insightly.php /home/deploy/wp-safety.org/data/plugin-versions/cf7-insightly/1.1.6/cf7-insightly.php
--- /home/deploy/wp-safety.org/data/plugin-versions/cf7-insightly/1.1.5/cf7-insightly.php	2025-05-22 11:22:26.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/cf7-insightly/1.1.6/cf7-insightly.php	2026-02-23 16:56:48.000000000 +0000
@@ -2,7 +2,7 @@
 /**
 * Plugin Name: WP Contact Form Insightly
 * Description: Integrates Contact Form 7, Ninja Forms, <a href="https://wordpress.org/plugins/contact-form-entries/">Contact Form Entries Plugin</a> and many other forms with Insightly allowing form submissions to be automatically sent to your Insightly account 
-* Version: 1.1.5
+* Version: 1.1.6
 * Requires at least: 3.8
 * Author URI: https://www.crmperks.com
 * Plugin URI: https://www.crmperks.com/plugins/contact-form-plugins/contact-form-insightly-plugin/
@@ -24,7 +24,7 @@
   public  $crm_name = "insightly";
   public  $id = "vxcf_insightly";
   public  $domain = "vxcf-insightly";
-  public  $version = "1.1.5";
+  public  $version = "1.1.6";
   public  $update_id = "6000001";
   public  $min_cf_version = "1.0";
   public $type = "vxcf_insightly";
@@ -118,18 +118,7 @@
   add_action('init', array($this,'init'));
        //loading translations
 load_plugin_textdomain('contact-form-insightly-crm', FALSE,  $this->plugin_dir_name(). '/languages/' );
-  
-  self::$db_version=get_option($this->type."_version");
-  if(self::$db_version != $this->version && current_user_can( 'manage_options' )){
-  $data=$this->get_data_object();
-  $data->update_table();
-  update_option($this->type."_version", $this->version);
-  //add post permissions
-  require_once(self::$path . "includes/install.php"); 
-  $install=new vxcf_insightly_install();
-  $install->create_roles();   
-
-  }
+$this->maybe_install(true);  
 }
   
   }
@@ -149,6 +138,27 @@
 self::$plugin->instance();
 }
 } }
+public function maybe_install($version_check=false){
+    
+  if(current_user_can( 'manage_options' )){
+  self::$db_version=get_option($this->type."_version");
+     $do_install=false;
+      if($version_check == false){
+        $do_install=true;  
+      }else if(self::$db_version != $this->version){
+        $do_install=true;   
+      }
+  if($do_install){
+  $data=$this->get_data_object();
+  $data->update_table();
+  update_option($this->type."_version", $this->version);
+  //add post permissions
+  require_once(self::$path . "includes/install.php"); 
+  $install=new vxcf_insightly_install();
+  $install->create_roles();   
+  }
+  } 
+}
 
  public function form_submitted($form){ 
 
@@ -508,29 +518,6 @@
   echo wp_kses_post($message) ;
   echo '</p></div>';
   } 
-
-
-  /**
-  * create tables and roles
-  * 
-  */
-  public function install(){
-      
-  if(current_user_can( 'manage_options' )){
-  self::$db_version=get_option($this->type."_version");
-  if(self::$db_version != $this->version){
-  $data=$this->get_data_object();
-  $data->update_table();
-  update_option($this->type."_version", $this->version);
-  //add post permissions
-  require_once(self::$path . "includes/install.php"); 
-  $install=new vxcf_insightly_install();
-  $install->create_roles();   
-
-  }
-
-  } 
-  }
 /**
 * Contact Form status
 * 
@@ -1275,6 +1262,7 @@
   */
   public function activate(){ 
 $this->plugin_api(true);
+$this->maybe_install();
 do_action('plugin_status_'.$this->type,'activate');  
   }
     /**
@@ -1414,6 +1414,11 @@
   * 
   */
   public function log_detail(){
+          check_ajax_referer('vx_crm_ajax','vx_crm_ajax');
+      if(!current_user_can($this->id.'_read_logs')){
+  esc_html_e('You do not have permissions to access this page','cf7-insightly');    
+  return;
+  }
 $log_id=$this->post('id');
 $log=$this->data->get_log_by_id($log_id); 
   $data=json_decode($log['data'],true);

Exploit Outline

The exploit targets administrative AJAX actions that lack permission checks. An authenticated attacker with Subscriber-level access first obtains a valid WordPress nonce (often leaked in script data or accessible via hidden input fields in the plugin's dashboard pages if they are visible). The attacker then sends a POST request to `/wp-admin/admin-ajax.php`. By setting the 'action' parameter to a vulnerable callback like `log_detail_vxcf_insightly` or `update_feed_vxcf_insightly`, the attacker can retrieve sensitive log data or modify CRM integration settings, as the backend handler fails to verify if the user possesses administrative capabilities before executing the request logic.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.