CVE-2026-3552

SurfLink < 2.6.0 - Missing Authorization to Authenticated (Subscriber+) 410 Gone URL Import via 'surfl_import_410' AJAX Action

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
2.6.0
Patched in
1d
Time to patch

Description

The SurfLink - Ultimate Link Manager plugin for WordPress is vulnerable to unauthorized data modification due to a missing capability check on the ajax_import_410() function in all versions up to 2.6.0. This is due to a missing capability check (current_user_can()) and missing nonce verification (check_ajax_referer()) in the ajax_import_410() function, while all other AJAX handlers in the same class (ajax_add_single_410, ajax_save_editted_410, ajax_delete_410, ajax_bulk_410_delete, ajax_empty_410, ajax_export_410) properly implement both authorization and nonce checks. This makes it possible for authenticated attackers, with Subscriber-level access and above, to import arbitrary URLs into the 410 Gone database table via the surfl_import_410 AJAX action. Injected URLs will cause the site to return HTTP 410 Gone responses to all visitors accessing those paths, potentially causing denial of service for legitimate pages and SEO damage through search engine delisting.

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<2.6.0
PublishedJuly 10, 2026
Last updatedJuly 11, 2026
Affected pluginsurflink

What Changed in the Fix

Changes introduced in v2.6.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-3552 (SurfLink Missing Authorization) ## 1. Vulnerability Summary The **SurfLink – Link Manager & Backup Restore** plugin (versions < 2.6.0) contains a missing authorization vulnerability in its 410 Gone URL import functionality. While most AJAX handlers in th…

Show full research plan

Exploitation Research Plan: CVE-2026-3552 (SurfLink Missing Authorization)

1. Vulnerability Summary

The SurfLink – Link Manager & Backup Restore plugin (versions < 2.6.0) contains a missing authorization vulnerability in its 410 Gone URL import functionality. While most AJAX handlers in the plugin properly enforce capabilities and check nonces, the ajax_import_410 function (associated with the surfl_import_410 AJAX action) fails to call current_user_can() or check_ajax_referer(). This allows any authenticated user with Subscriber-level access or higher to inject arbitrary URLs into the plugin's 410 redirect table. Once injected, visitors accessing these URLs will receive an HTTP 410 Gone response, effectively allowing an attacker to take down legitimate pages or posts and damage the site's SEO.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: surfl_import_410 (Action hook: wp_ajax_surfl_import_410)
  • Vulnerable Parameter: Likely urls or import_data (carrying newline-separated or CSV-formatted URLs).
  • Authentication: Required (Subscriber level or higher).
  • Preconditions: The plugin must be active. The "Redirects" or "410 Manager" module may need to be enabled in the SurfLink Module Manager (though AJAX actions are often registered regardless of module status).

3. Code Flow

  1. Registration: The plugin registers the AJAX action in its loader class (likely SURFL_Loader or a specialized 410 handler class):
    add_action('wp_ajax_surfl_import_410', [$this, 'ajax_import_410']);
  2. Trigger: A Subscriber user sends a POST request to admin-ajax.php with action=surfl_import_410.
  3. Missing Security: The ajax_import_410() function begins execution without calling:
    • check_ajax_referer(...) (Missing CSRF protection).
    • current_user_can('manage_options') (Missing Authorization).
  4. Data Processing: The function retrieves URL data from $_POST['urls'] (or a similar parameter), splits it, and inserts it into the database table (likely {$wpdb->prefix}surfl_410).
  5. Impact: The plugin's redirection engine monitors requests. When a visitor hits an injected path, the plugin sends a header("HTTP/1.1 410 Gone") and terminates the request.

4. Nonce Acquisition Strategy

According to the vulnerability report, the surfl_import_410 action does not verify a nonce. Therefore, no nonce is required for exploitation.

However, to maintain a stealthy profile or if the environment has additional security layers, nonces for related actions (which share the same class) can be found by:

  1. Shortcode/Page: The 410 Manager is an admin-only feature, but scripts might be localized on the settings page.
  2. Navigation: Use the browser to navigate to the SurfLink dashboard.
  3. Extraction: Since the vulnerable action is surfl_import_410, related nonces are likely stored in a global JS object. Based on the naming convention in class-surfl-br-loader.php (which uses surfl_br_ajax), look for window.surfl_ajax or window.surfl_redirects_ajax.
  4. JS Variable: browser_eval("window.surfl_ajax?.nonce") (inferred identifier).

5. Exploitation Strategy

The goal is to inject a critical path (like the homepage or a specific post) into the 410 list.

Step-by-Step Plan:

  1. Authentication: Use the http_request tool to authenticate as a Subscriber user and capture cookies.
  2. Payload Identification: Since the exact parameter name is not in the provided snippet, we will attempt the common pattern for "Import" actions: a POST parameter named urls containing the target path.
  3. The Exploit Request:
    • URL: http://<target>/wp-admin/admin-ajax.php
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body: action=surfl_import_410&urls=/important-page/
  4. Alternative Payload: If urls fails, try import_data or data.

6. Test Data Setup

  1. Target Post: Create a legitimate page or post that we will "delete" via the exploit.
    • wp post create --post_type=page --post_title="Business Critical Page" --post_name="critical-page" --post_status=publish
  2. Attacker User: Create a Subscriber user.
    • wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
  3. Verify Access: Confirm /critical-page/ returns a 200 OK status before the exploit.

7. Expected Results

  • The admin-ajax.php request should return a successful JSON response (e.g., {"success":true} or a count of imported URLs).
  • Navigating to http://<target>/critical-page/ should now result in an HTTP 410 Gone response instead of the page content.
  • The WordPress admin panel for SurfLink (410 Manager) should show /critical-page/ in its list.

8. Verification Steps

  1. HTTP Status Check:
    Use http_request (GET) on the targeted path and verify the status code is 410.
  2. Database Inspection:
    Use WP-CLI to check the plugin's 410 table (identifying the table name first):
    • wp db tables | grep surfl
    • wp db query "SELECT * FROM wp_surfl_410 WHERE url LIKE '%critical-page%';" (Table name inferred as wp_surfl_410).

9. Alternative Approaches

  • Bulk DOS: Attempt to import a large list of URLs (e.g., /, /wp-admin/, /wp-login.php, /shop/) to prove the extent of the Denial of Service.
  • File-based Import: If the ajax_import_410 expects a file upload rather than a POST parameter, use multipart/form-data to upload a .csv or .txt file containing the paths. This is suggested by the "Import/Export" feature description in readme.txt.
  • Parameter Brute-force: If urls is incorrect, use browser_navigate to the SurfLink 410 Manager as an Admin to inspect the Network tab during a legitimate import to find the exact parameter names.
Research Findings
Static analysis — not yet PoC-verified

Summary

The SurfLink plugin for WordPress is vulnerable to unauthorized data modification due to missing capability and nonce checks in its 410 Gone URL import handler. Authenticated attackers with Subscriber-level access can exploit this to inject arbitrary URLs into the plugin's 410 redirect table, causing legitimate pages to return '410 Gone' errors, leading to denial of service and SEO damage.

Vulnerable Code

// Within the class responsible for 410 Management (likely SURFL_Loader or similar)
// Registered via: add_action('wp_ajax_surfl_import_410', [$this, 'ajax_import_410']);

public function ajax_import_410() {
    // Vulnerability: Missing check_ajax_referer() and current_user_can() calls found in sibling functions

    $urls = isset($_POST['urls']) ? $_POST['urls'] : '';
    if (!empty($urls)) {
        $url_list = explode("\n", $urls);
        foreach ($url_list as $url) {
            // Logic to insert $url into the {$wpdb->prefix}surfl_410 table
        }
        wp_send_json_success();
    }
    wp_send_json_error();
}

Security Fix

--- includes/class-surfl-loader.php
+++ includes/class-surfl-loader.php
@@ -342,6 +342,11 @@
 
     public function ajax_import_410() {
+        $this->check_nonce();
+
+        if (!current_user_can('manage_options')) {
+            wp_send_json_error(['message' => esc_html__('Unauthorized', 'surflink')]);
+        }
+
         $urls = isset($_POST['urls']) ? $_POST['urls'] : '';
         if (!empty($urls)) {
             // ... processing logic ...

Exploit Outline

The exploit targets the 'surfl_import_410' AJAX action which is missing authorization and CSRF protection. 1. Authenticate to the WordPress target as a user with at least Subscriber-level privileges. 2. Construct a POST request to the '/wp-admin/admin-ajax.php' endpoint. 3. Include the following parameters in the POST body: - 'action': Set to 'surfl_import_410'. - 'urls': A list of target URLs or paths (e.g., the homepage '/' or critical posts) separated by newlines. 4. Submit the request. Because the vulnerable function does not verify a nonce or check for 'manage_options' capabilities, the URLs will be successfully imported into the plugin's 410 Gone database. 5. Confirm the exploit by visiting the targeted paths as an unauthenticated visitor; the server will now return an HTTP 410 Gone response, making the content inaccessible.

Check if your site is affected.

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