BIALTY - Bulk Image Alt Text (Alt tag, Alt Attribute) with Yoast SEO + WooCommerce <= 2.2.1 - Authenticated (Contributor+) Stored Cross-Site Scripting
Description
The BIALTY - Bulk Image Alt Text (Alt tag, Alt Attribute) with Yoast SEO + WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'bialty_cs_alt' post meta in all versions up to, and including, 2.2.1 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with contributor level access and above, to inject arbitrary web scripts in pages that will execute whenever an administrator accesses the post editor.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=2.2.1Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-15019 ## 1. Vulnerability Summary The **Bulk Auto Image Alt Text (BIALTY)** plugin (<= 2.2.1) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fails to sanitize the `bialty_cs_alt` post meta value when it is …
Show full research plan
Exploitation Research Plan - CVE-2025-15019
1. Vulnerability Summary
The Bulk Auto Image Alt Text (BIALTY) plugin (<= 2.2.1) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin fails to sanitize the bialty_cs_alt post meta value when it is saved and fails to escape it when it is rendered within the WordPress post editor. A user with Contributor level permissions or higher can create a post, inject a malicious script into this meta field, and have that script execute in the browser of any user (specifically an Administrator) who later edits that post.
2. Attack Vector Analysis
- Vulnerable Endpoint:
wp-admin/post.php(Standard WordPress post update handler). - Vulnerable Parameter:
bialty_cs_alt(Typically sent via POST during post save/update). - Authentication Level: Contributor or higher. Contributors can edit their own posts and manage post meta associated with them.
- Preconditions: The plugin must be active. The attacker needs access to the post editor for a post type that supports the BIALTY meta box (usually
post,page, orproduct).
3. Code Flow (Inferred)
- Input Registration: The plugin registers a metabox in the post editor via the
add_meta_boxeshook. - Display (Sink): The metabox callback function retrieves the meta value using
get_post_meta($post->ID, 'bialty_cs_alt', true). It likely outputs this value into an HTML input field (e.g.,<input value="...">) without usingesc_attr(). - Saving (Source): The plugin listens for post save events via the
save_postorwp_insert_posthook. - Processing: The handler function (e.g.,
bialty_save_meta_box_data) checks if$_POST['bialty_cs_alt']is set. - Storage: It calls
update_post_meta($post_id, 'bialty_cs_alt', $_POST['bialty_cs_alt'])without applying sanitization functions likesanitize_text_field().
4. Nonce Acquisition Strategy
The BIALTY plugin likely uses a custom nonce within its metabox to validate the meta submission, in addition to the standard WordPress _wpnonce.
- Create Content: As a Contributor, create a new draft post:
wp post create --post_type=post --post_status=draft --post_title="XSS Test" --post_author=CONTRIBUTOR_ID - Navigate to Editor: Use the
browser_navigatetool to go to the edit page for that post:/wp-admin/post.php?post=POST_ID&action=edit. - Extract Nonce: The metabox will contain a hidden nonce field. Use
browser_evalto find the BIALTY-specific nonce:browser_eval("document.querySelector('input[name*=\"bialty\"]')?.value")- Alternatively, search the HTML for a field likely named
bialty_meta_box_nonceor similar.
- Standard Nonce: The standard
_wpnoncefor theeditpostaction is also required and can be found via:browser_eval("document.querySelector('#_wpnonce')?.value")
5. Exploitation Strategy
Step 1: Authentication and Post Creation
- Authenticate as a Contributor.
- Create a post to obtain a
post_ID.
Step 2: Injecting the Payload
Send a POST request to wp-admin/post.php to update the post meta.
- URL:
https://TARGET/wp-admin/post.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Body Parameters:
action:editpostpost_ID:[POST_ID]_wpnonce:[EXTRACTED_WP_NONCE]bialty_meta_box_nonce:[EXTRACTED_BIALTY_NONCE](if applicable)bialty_cs_alt:"><script>alert(document.cookie)</script>post_title:XSS Test
Step 3: Triggering the Execution
- Log in as an Administrator.
- Navigate to the post editor for the infected post:
/wp-admin/post.php?post=[POST_ID]&action=edit. - The script will execute because the value is rendered unsanitized in the BIALTY metabox field.
6. Test Data Setup
- Install and activate the
bulk-image-alt-text-with-yoastplugin (version <= 2.2.1). - Create a user with the
contributorrole. - (Optional) Install Yoast SEO or WooCommerce if the plugin requires their presence to activate the meta boxes (the vulnerability description suggests the plugin works with them).
7. Expected Results
- The
update_post_metacall succeeds. - The database now contains the raw HTML payload in the
wp_postmetatable for the keybialty_cs_alt. - When an Admin views the post editor, the HTML source of the page shows the injected payload breaking out of the input attribute:
<input ... value=""><script>alert(document.cookie)</script>"> - A JavaScript alert containing the session cookie appears in the Admin's browser.
8. Verification Steps
- Check Database via CLI:
wp post meta get [POST_ID] bialty_cs_alt
Confirm the output matches the payload exactly. - Verify Payload in HTML:
Navigate to the edit page as Admin and check if the payload exists in the response body.http_request(url="/wp-admin/post.php?post=POST_ID&action=edit", method="GET")
Check the response for the string:"><script>alert(document.cookie)</script>.
9. Alternative Approaches
- WooCommerce Product: If the standard post metabox is not vulnerable, try the same process with a
productpost type if WooCommerce is installed, as the plugin specifically targets WooCommerce. - AJAX Save: Check if the plugin has an AJAX handler for "Bulk" operations that might update the meta field via
admin-ajax.php. Search forwp_ajax_bialty_actions in the code. - Payload Variations:
" onmouseover="alert(1)(Attribute injection)</textarea><script>alert(1)</script>(If the field is a textarea)
Summary
The BIALTY plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'bialty_cs_alt' post meta field. This occurs because the plugin fails to sanitize the meta value upon saving and fails to escape it when rendering it within a metabox in the WordPress post editor. This allows authenticated users with Contributor-level access to inject malicious scripts that execute in the browser of an administrator viewing the affected post.
Vulnerable Code
// Inferred metabox rendering function $bialty_cs_alt = get_post_meta($post->ID, 'bialty_cs_alt', true); ?> <div class="bialty-metabox-field"> <label for="bialty_cs_alt">Custom Alt Text:</label> <input type="text" name="bialty_cs_alt" id="bialty_cs_alt" value="<?php echo $bialty_cs_alt; ?>" /> </div> <?php --- // Inferred save_post handler function if (isset($_POST['bialty_cs_alt'])) { update_post_meta($post_id, 'bialty_cs_alt', $_POST['bialty_cs_alt']); }
Security Fix
@@ -10,7 +10,7 @@ - <input type="text" name="bialty_cs_alt" id="bialty_cs_alt" value="<?php echo $bialty_cs_alt; ?>" /> + <input type="text" name="bialty_cs_alt" id="bialty_cs_alt" value="<?php echo esc_attr($bialty_cs_alt); ?>" /> @@ -20,5 +20,5 @@ -if (isset($_POST['bialty_cs_alt'])) { - update_post_meta($post_id, 'bialty_cs_alt', $_POST['bialty_cs_alt']); +if (isset($_POST['bialty_cs_alt'])) { + update_post_meta($post_id, 'bialty_cs_alt', sanitize_text_field($_POST['bialty_cs_alt'])); }
Exploit Outline
1. Authenticate as a Contributor level user. 2. Create a new post or edit an existing one. 3. Identify the BIALTY metabox in the editor or prepare a POST request to wp-admin/post.php with action=editpost. 4. Include the parameter 'bialty_cs_alt' in the POST body with a payload designed to break out of an HTML attribute, such as: "><script>alert(document.cookie)</script>. 5. Submit the request to save the post. The payload will be stored unsanitized in the wp_postmeta table. 6. As an Administrator, navigate to the post editor for the infected post. The script will execute because the plugin echoes the 'bialty_cs_alt' value directly into the 'value' attribute of an input tag without escaping.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.