CVE-2026-1753

Gutena Forms – Contact Form, Survey Form, Feedback Form, Booking Form, and Custom Form Builder < 1.6.1 - Missing Authorization to Authenticated (Contributor+) Settings Update

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

Description

The Gutena Forms – Contact Form, Survey Form, Feedback Form, Booking Form, and Custom Form Builder plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to 1.6.1 (exclusive). This makes it possible for authenticated attackers, with Contributor-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.6.1
PublishedMarch 12, 2026
Last updatedMarch 19, 2026
Affected plugingutena-forms

What Changed in the Fix

Changes introduced in v1.6.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: Gutena Forms Missing Authorization (CVE-2026-1753) ## 1. Vulnerability Summary The **Gutena Forms** plugin for WordPress is vulnerable to unauthorized settings updates due to missing capability checks in its administrative interfaces. Specifically, in versions prior to…

Show full research plan

Exploitation Research Plan: Gutena Forms Missing Authorization (CVE-2026-1753)

1. Vulnerability Summary

The Gutena Forms plugin for WordPress is vulnerable to unauthorized settings updates due to missing capability checks in its administrative interfaces. Specifically, in versions prior to 1.6.1, certain functions responsible for updating global plugin settings (such as reCAPTCHA keys, Turnstile settings, and global form messages) are accessible to any authenticated user with Contributor-level permissions or higher. This occurs because the permission check (likely in the REST API or AJAX handlers) uses a weak capability like edit_posts instead of manage_options.

2. Attack Vector Analysis

  • Endpoint: WordPress REST API endpoint /wp-json/gutena-forms/v1/settings.
  • Method: POST
  • Authentication: Authenticated (Contributor+)
  • Vulnerable Parameter: The request body (JSON) containing settings keys to be updated.
  • Payload: A JSON object overwriting sensitive global options such as gutena_forms_grecaptcha or gutena_forms_turnstile.
  • Preconditions:
    • The plugin version must be < 1.6.1.
    • An attacker must have credentials for a user with the Contributor role.

3. Code Flow

  1. Entry Point: The plugin initializes its REST API in gutena-forms.php by including includes/rest-api/class-rest-api.php.
  2. Registration: Inside class-rest-api.php (referenced in includes/rest-api/class-rest-api.php), a route is registered: register_rest_route('gutena-forms/v1', '/settings', ...).
  3. Weak Check: The permission_callback for this route incorrectly uses current_user_can('edit_posts') or lacks a check entirely, allowing any user who can edit posts (Contributors and above) to pass the authorization phase.
  4. Execution: The callback function (e.g., update_settings) receives the JSON payload and calls update_option() for keys like gutena_forms_grecaptcha without further verification.
  5. Sink: update_option() in the WordPress database.

4. Nonce Acquisition Strategy

The WordPress REST API requires a standard wp_rest nonce for POST requests from authenticated users.

  1. Access Admin Context: Even if a Contributor cannot see the Gutena Forms menu, they can access the standard post editor.
  2. Navigate: Use the browser to navigate to /wp-admin/post-new.php.
  3. Extract Nonce: The standard WordPress REST API nonce is stored in the window.wpApiSettings.nonce variable.
  4. JavaScript Tool:
    browser_eval("window.wpApiSettings.nonce")
    
  5. Alternative: If the plugin enqueues its own settings scripts, check window.gutena_forms_admin?.nonce (inferred).

5. Exploitation Strategy

Step 1: Authentication

Login as a user with the Contributor role.

Step 2: Nonce Extraction

Navigate to the post editor and extract the REST nonce.

  • URL: /wp-admin/post-new.php
  • Action: Extract window.wpApiSettings.nonce.

Step 3: Malicious Settings Update

Send a POST request to the REST API to update the reCAPTCHA settings.

  • URL: /wp-json/gutena-forms/v1/settings
  • Method: POST
  • Headers:
    • Content-Type: application/json
    • X-WP-Nonce: [EXTRACTED_NONCE]
  • Body:
    {
      "gutena_forms_grecaptcha": {
        "site_key": "PWNED_SITE_KEY",
        "secret_key": "PWNED_SECRET_KEY",
        "enabled": "1"
      }
    }
    

Step 4: Verification

Confirm the setting was updated using WP-CLI.

6. Test Data Setup

  1. Target Version: Ensure Gutena Forms v1.6.0 is installed.
  2. User Creation: Create a Contributor user:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
    
  3. Optional: Initialize the default settings if they don't exist:
    wp option add gutena_forms_grecaptcha '{"site_key": "original", "secret_key": "original"}' --format=json
    

7. Expected Results

  • The REST API should return a 200 OK or 201 Created response.
  • The response body should confirm the settings were updated.
  • The global gutena_forms_grecaptcha option in the database should now contain the attacker's values.

8. Verification Steps

After performing the HTTP request, use WP-CLI to verify the change:

wp option get gutena_forms_grecaptcha --format=json

Success Condition: The output shows "site_key": "PWNED_SITE_KEY".

9. Alternative Approaches

If the REST API route is different or disabled, check for an AJAX handler:

  • Action: wp_ajax_gutena_forms_save_settings (inferred).
  • Endpoint: /wp-admin/admin-ajax.php.
  • Parameters: action=gutena_forms_save_settings&security=[NONCE]&settings[gutena_forms_grecaptcha][site_key]=PWNED.
  • Nonce Source: Search page source for gutena_forms_admin localization in wp-admin/admin.php?page=gutena-forms (if accessible) or via block editor settings.

Another target option for verification:

  • Option Name: gutena_forms_messages
  • Payload: {"gutena_forms_messages": {"success": "Your site has been hacked!"}}
Research Findings
Static analysis — not yet PoC-verified

Summary

The Gutena Forms plugin for WordPress is vulnerable to unauthorized settings updates and arbitrary option overwrites due to missing capability checks and insufficient validation of user-controlled option keys. Authenticated attackers with Contributor-level permissions can exploit this by manipulating the formID parameter during form saving, allowing them to overwrite sensitive global options such as reCAPTCHA keys or site configuration.

Vulnerable Code

// gutena-forms.php (around line 465 in v1.6.0)
// filter for formSchema
$formSchema_filtered = apply_filters( 'gutena_forms_save_form_schema', $formSchema, $formSchema['form_attrs']['formID'], $gutena_form_ids );
//Save form schema
update_option(
    sanitize_key( $formSchema['form_attrs']['formID'] ),
    $this->sanitize_array( $formSchema_filtered, true )
);

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/gutena-forms/1.6.0/gutena-forms.php /home/deploy/wp-safety.org/data/plugin-versions/gutena-forms/1.6.1/gutena-forms.php
--- /home/deploy/wp-safety.org/data/plugin-versions/gutena-forms/1.6.0/gutena-forms.php	2026-01-21 04:25:20.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/gutena-forms/1.6.1/gutena-forms.php	2026-02-17 07:05:32.000000000 +0000
@@ -4,7 +4,7 @@
  * Description:       Gutena Forms is the easiest way to create forms inside the WordPress block editor. Our plugin does not use jQuery and is lightweight, so you can rest assured that it won’t slow down your website. Instead, it allows you to quickly and easily create custom forms right inside the block editor.
  * Requires at least: 6.5
  * Requires PHP:      5.6
- * Version:           1.6.0
+ * Version:           1.6.1
  * Author:            Gutena Forms
  * Author URI:        https://gutenaforms.com
  * License:           GPL-2.0-or-later
@@ -42,7 +42,44 @@
  * Plugin version.
  */
 if ( ! defined( 'GUTENA_FORMS_VERSION' ) ) {
-	define( 'GUTENA_FORMS_VERSION', '1.5.1' );
+	define( 'GUTENA_FORMS_VERSION', '1.6.1' );
+}
+
+/**
+ * Option name prefix for form schema (security: prevents arbitrary option overwrite).
+ */
+if ( ! defined( 'GUTENA_FORMS_SCHEMA_OPTION_PREFIX' ) ) {
+	define( 'GUTENA_FORMS_SCHEMA_OPTION_PREFIX', 'gutena_forms_schema_' );
+}
+
+if ( ! function_exists( 'gutena_forms_get_form_schema_option' ) ) {
+	/**
+	 * Get form schema option value. Checks non-prefixed first, then prefixed; if both exist, returns prefixed.
+	 *
+	 * @param string $form_id Form ID (option key).
+	 * @param mixed  $default Default if neither option exists.
+	 * @return mixed Form schema array or $default.
+	 */
+	function gutena_forms_get_form_schema_option( $form_id, $default = false ) {
+		$form_id = sanitize_key( $form_id );
+		if ( '' === $form_id ) {
+			return $default;
+		}
+		$non_prefixed = get_option( $form_id, null );
+		$prefixed     = get_option( GUTENA_FORMS_SCHEMA_OPTION_PREFIX . $form_id, null );
+		$has_non_prefixed = ( null !== $non_prefixed );
+		$has_prefixed     = ( null !== $prefixed );
+		if ( $has_non_prefixed && $has_prefixed ) {
+			return $prefixed;
+		}
+		if ( $has_prefixed ) {
+			return $prefixed;
+		}
+		if ( $has_non_prefixed ) {
+			return $non_prefixed;
+		}
+		return $default;
+	}
 }
 
 if ( ! function_exists( 'gutena_forms__fs' ) ) :
@@ -463,9 +500,9 @@
 						}
 						//filter for formSchema
 						$formSchema_filtered = apply_filters( 'gutena_forms_save_form_schema', $formSchema, $formSchema['form_attrs']['formID'], $gutena_form_ids );
-						//Save form schema
+						//Save form schema (prefixed option name prevents arbitrary option overwrite)
 						update_option(
-							sanitize_key( $formSchema['form_attrs']['formID'] ),
+							GUTENA_FORMS_SCHEMA_OPTION_PREFIX . sanitize_key( $formSchema['form_attrs']['formID'] ),
 							$this->sanitize_array( $formSchema_filtered, true )
 						);

Exploit Outline

1. Authenticate as a user with Contributor-level access or higher. 2. Access the WordPress block editor (e.g., create a new post at `/wp-admin/post-new.php`). 3. Insert a Gutena Form block and observe the outgoing REST API or AJAX request used to save the form configuration. 4. Intercept the save request and modify the `formID` attribute inside the `form_attrs` object to match a sensitive WordPress option name, such as `gutena_forms_grecaptcha` (to disrupt security) or `users_can_register` (to enable registration). 5. Include the desired malicious value for that option in the `formSchema` payload. 6. Submit the request; the server will execute `update_option()` using the attacker-supplied key, thereby overwriting the site setting because the capability check only verifies if the user can save posts (Contributor level), not manage global options.

Check if your site is affected.

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