TS Poll – Survey, Versus Poll, Image Poll, Video Poll <= 2.5.5 - Authenticated (Editor+) Server-Side Request Forgery
Description
The TS Poll – Survey, Versus Poll, Image Poll, Video Poll plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 2.5.5. This makes it possible for authenticated attackers, with Editor-level access and above, to make web requests to arbitrary locations originating from the web application which can be used to query and modify information from internal services.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:L/I:L/A:NTechnical Details
This research plan outlines the steps to identify and exploit the Authenticated Server-Side Request Forgery (SSRF) vulnerability in the **TS Poll – Survey, Versus Poll, Image Poll, Video Poll** plugin (<= 2.5.5). ### 1. Vulnerability Summary The TS Poll plugin for WordPress contains an SSRF vulnera…
Show full research plan
This research plan outlines the steps to identify and exploit the Authenticated Server-Side Request Forgery (SSRF) vulnerability in the TS Poll – Survey, Versus Poll, Image Poll, Video Poll plugin (<= 2.5.5).
1. Vulnerability Summary
The TS Poll plugin for WordPress contains an SSRF vulnerability accessible to users with Editor-level privileges or higher. The vulnerability exists because the plugin fails to properly validate or sanitize user-supplied URLs in a functionality that fetches remote content (likely related to image/video polls or poll imports). An attacker can leverage this to make the web server send requests to arbitrary internal or external locations.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php - Action:
tspoll_fetch_remote_dataorts_poll_get_video_meta(inferred). - Parameter: A URL parameter (e.g.,
url,video_url, orremote_path). - Authentication: Required (Editor+).
- Preconditions: The attacker must have a valid session cookie for a user with the
Editorrole.
3. Code Flow (Inferred)
- Entry Point: An AJAX action is registered via
add_action( 'wp_ajax_...', ... )in the plugin's admin initialization code (likelyadmin/class-ts-poll-admin.phporincludes/class-ts-poll.php). - Nonce Verification: The handler likely checks a nonce using
check_ajax_referer()orwp_verify_nonce(). - Source: User input is retrieved from
$_POST['url'](or similar). - Sink: The input is passed directly into a WordPress HTTP API function like
wp_remote_get()orwp_remote_request()without validation against a whitelist of allowed domains or internal IP ranges. - Output: The response from the remote request (status code, headers, or body) is often returned to the user via
wp_send_json_success().
4. Nonce Acquisition Strategy
Since this is an authenticated (Editor+) vulnerability, we must extract a valid nonce from the WordPress admin dashboard.
- Identify the Localized Script: The plugin likely uses
wp_localize_scriptto pass a nonce to its admin JS. - Target Page: Navigate to the "TS Poll" creation page (e.g.,
/wp-admin/admin.php?page=ts-poll-add-new). - Extraction:
- Log in as an Editor.
- Navigate to the TS Poll admin menu.
- Use
browser_evalto find the nonce in the global JS scope. - Likely JS Variable:
window.tspoll_admin_obj?.nonceorwindow.ts_poll_vars?.ajax_nonce(inferred).
5. Exploitation Strategy
The goal is to perform an SSRF to query internal services (e.g., the local web server or metadata services).
- Identify the vulnerable AJAX action: Search the plugin source for
wp_remote_getto find the exact action name and parameter. - Setup a Listener (Optional): Use a tool like Webhook.site to confirm external SSRF first.
- Craft the Request:
- URL:
http://<target-site>/wp-admin/admin-ajax.php - Method: POST
- Body:
action=TS_POLL_VULNERABLE_ACTION&nonce=NONCE_VALUE&url=http://127.0.0.1:80
- URL:
- Execute via
http_request:// Example Payload Structure { "method": "POST", "url": "http://localhost:8888/wp-admin/admin-ajax.php", "headers": { "Content-Type": "application/x-www-form-urlencoded", "Cookie": "wordpress_logged_in_..." }, "body": "action=ts_poll_fetch_remote&nonce=a1b2c3d4e5&url=http://169.254.169.254/latest/meta-data/" }
6. Test Data Setup
- User Creation: Create a user with the
Editorrole.wp user create editor_user editor@example.com --role=editor --user_pass=password123
- Internal Target: Ensure there is an internal service to hit (e.g., the standard WP instance itself or a simple file on the root).
7. Expected Results
- Successful SSRF: The response from
admin-ajax.phpwill contain data from the internal URL (e.g., the HTML of the local homepage or AWS metadata). - HTTP Response: Usually a
200 OKwith a JSON body where one of the keys contains the content of the requested URL.
8. Verification Steps
- Check Logs: Verify in the access logs of the target internal service that a request originated from the web server's own IP address.
- Confirm Content: Match the response body returned by the AJAX call with the known content of the internal resource.
9. Alternative Approaches
If wp_remote_get is not the sink, look for:
file_get_contents($url): If theallow_url_fopensetting is enabled in PHP, this is a common SSRF sink.curl_exec(): Used if the plugin implements its own CURL wrapper.- Blind SSRF: If the response is not returned, try to trigger a DNS request to an external collaborator (e.g., Burp Collaborator or Interactsh) to confirm the request was made.
10. Potential Action Strings to Search (Inferred)
Search the codebase for these strings to find the exact endpoint:
ts_poll_get_remotetspoll_fetch_urltspoll_video_dataimport_poll_from_urlget_image_from_url(check if used in Image Polls)
Summary
The TS Poll plugin for WordPress is vulnerable to Authenticated (Editor+) Server-Side Request Forgery (SSRF) in versions up to and including 2.5.5. This allows users with Editor-level access or higher to make the web server send requests to arbitrary internal or external locations, potentially exposing internal service data.
Vulnerable Code
// Inferred based on Research Plan findings in admin/class-ts-poll-admin.php add_action( 'wp_ajax_tspoll_fetch_remote_data', 'tspoll_fetch_remote_data_callback' ); function tspoll_fetch_remote_data_callback() { check_ajax_referer( 'tspoll_nonce', 'nonce' ); $url = $_POST['url']; // The vulnerability exists here because $url is passed directly to wp_remote_get $response = wp_remote_get( $url ); $body = wp_remote_retrieve_body( $response ); wp_send_json_success( $body ); wp_die(); }
Security Fix
@@ -10,6 +10,11 @@ function tspoll_fetch_remote_data_callback() { check_ajax_referer( 'tspoll_nonce', 'nonce' ); - $url = $_POST['url']; + $url = esc_url_raw( $_POST['url'] ); + if ( ! wp_http_validate_url( $url ) ) { + wp_send_json_error( 'Invalid URL' ); + } $response = wp_remote_get( $url );
Exploit Outline
An attacker with Editor-level authentication must first obtain a valid AJAX nonce from the TS Poll admin dashboard (likely via a localized script variable like 'window.tspoll_admin_obj.nonce'). Then, the attacker sends a POST request to '/wp-admin/admin-ajax.php' with the action set to 'tspoll_fetch_remote_data' (or a similar remote-fetching action) and a 'url' parameter targeting an internal resource, such as 'http://169.254.169.254/latest/meta-data/'. The server performs the request and returns the resulting content in the AJAX response.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.