Everest Forms <= 3.4.3 - Unauthenticated PHP Object Injection via Form Entry Metadata
Description
The Everest Forms plugin for WordPress is vulnerable to PHP Object Injection in all versions up to, and including, 3.4.3 via deserialization of untrusted input from form entry metadata. This is due to the html-admin-page-entries-view.php file calling PHP's native unserialize() on stored entry meta values without passing the allowed_classes parameter. This makes it possible for unauthenticated attackers to inject a serialized PHP object payload through any public Everest Forms form field. The payload survives sanitize_text_field() sanitization (serialization control characters are not stripped) and is stored in the wp_evf_entrymeta database table. When an administrator views entries or views an individual entry, the unsafe unserialize() call processes the stored data without class restrictions.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HTechnical Details
What Changed in the Fix
Changes introduced in v3.4.4
Source Code
WordPress.org SVN# Research Plan: CVE-2026-3296 - Everest Forms Unauthenticated PHP Object Injection ## 1. Vulnerability Summary The **Everest Forms** plugin (versions <= 3.4.3) is vulnerable to **PHP Object Injection** due to the insecure use of the native PHP `unserialize()` function. The vulnerability exists in …
Show full research plan
Research Plan: CVE-2026-3296 - Everest Forms Unauthenticated PHP Object Injection
1. Vulnerability Summary
The Everest Forms plugin (versions <= 3.4.3) is vulnerable to PHP Object Injection due to the insecure use of the native PHP unserialize() function. The vulnerability exists in the way form entry metadata is retrieved and displayed in the WordPress administrative dashboard.
An unauthenticated attacker can submit a form containing a serialized PHP object payload in any field. This payload is stored in the wp_evf_entrymeta table. When an administrator views the "Entries" section of the plugin, the html-admin-page-entries-view.php file processes this stored metadata using unserialize() without restricting the allowed classes. This allows the execution of arbitrary code if a suitable POP (Property-Oriented Programming) gadget chain is present in the environment (e.g., within WordPress core or other active plugins).
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php(Front-end form submission). - Action:
everest_forms_submit_form(inferred action for form submission). - Vulnerable Parameter: Any form field parameter (e.g.,
form_fields[field_id]). - Authentication: None (Unauthenticated).
- Preconditions:
- At least one Everest Forms form must be published and accessible on the frontend.
- An administrator must eventually view the submitted entry in the WP-Admin area.
3. Code Flow
Submission (Unauthenticated):
- The user submits a form on the frontend.
- The request is processed by
EVF_Frontend_Form_Handler::submit_form()(or similar class responsible for submission). - The plugin iterates through fields and applies
sanitize_text_field(). - Critical Note:
sanitize_text_field()does not remove characters critical to PHP serialization (likeO:,a:,{}). - The data is saved into the database table
wp_evf_entrymeta.
Triggering (Admin):
- Administrator navigates to
wp-admin/admin.php?page=evf-entries. - The plugin loads
includes/admin/views/html-admin-page-entries-view.php. - The code retrieves entry meta:
$entry_meta = $wpdb->get_results(...). - The code iterates through the meta values and calls
unserialize( $meta_value->meta_value ). - The PHP Object Injection is triggered at this point.
- Administrator navigates to
4. Nonce Acquisition Strategy
Form submissions in Everest Forms are protected by a frontend nonce.
- Identify the Script/Variable: Everest Forms typically localizes parameters under the handle
everest-forms-frontend. - Target Variable:
window.evf_frontend_params(inferred). - Target Key:
nonce. - Acquisition Steps:
- Use WP-CLI to create a form and a page containing that form's shortcode.
- Use the
browser_navigatetool to go to the newly created page. - Use
browser_evalto extract the nonce:window.evf_frontend_params?.nonce || document.querySelector('#everest-forms-nonce')?.value - Note: If the
CleanTalkaddon is active, it enqueues a different nonce (everest_forms_clean_talk_nonce), but this is for admin settings and likely not the submission nonce.
5. Exploitation Strategy
Step 1: Payload Selection
Since we need to confirm the injection, we will use a gadget chain that produces an observable side effect. A common gadget for WordPress is GuzzleHttp\Cookie\CookieJar (if available) or a generic __destruct trigger that logs to a file. For initial PoC, a "dummy" serialized object can be used to confirm if unserialize is reached.
Payload Example (Generic):O:8:"stdClass":1:{s:3:"abc";s:3:"def";}
Step 2: Submission Request
Submit the payload via the AJAX submission endpoint.
- URL:
http://<target>/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Parameters:
action:everest_forms_submit_formeverest_forms[id]:<form_id>everest_forms_nonce:<extracted_nonce>form_fields[<field_id>]:O:8:"stdClass":1:{s:3:"abc";s:3:"def";}(URL-encoded)
Step 3: Triggering
Login as an administrator and access the entry viewer.
- URL:
http://<target>/wp-admin/admin.php?page=evf-entries&view=entries&form_id=<form_id>
6. Test Data Setup
- Create a Form:
(Note: Ifwp evf-form create --title="Exploit Form" --status="publish"evf-formcommand doesn't exist, usewp post createwith post_typeeverest_formsand appropriate JSON inpost_content.) - Extract Form ID and Field ID: Retrieve the ID from the previous command or
wp post list --post_type=everest_forms. - Create a Public Page:
wp post create --post_type=page --post_title="Contact" --post_content='[everest_form id="<form_id>"]' --post_status="publish"
7. Expected Results
- The form submission should return a success JSON:
{"success":true,...}. - Upon viewing entries as an admin, if a malicious gadget is used (e.g., one that calls
wp_die()), the admin page will crash or display thewp_diemessage, confirming execution. - If using a dummy object, we can verify it was stored correctly in the database.
8. Verification Steps
- Database Check: Verify the payload is stored in the
wp_evf_entrymetatable without being mangled.wp db query "SELECT * FROM $(wp db prefix)evf_entrymeta WHERE meta_value LIKE 'O:%';" - Execution Check: Use a gadget that creates a file in
wp-content/and verify its existence usingls.
9. Alternative Approaches
- Direct POST: Some versions allow submitting directly to the page containing the shortcode via a standard
POSTrequest (non-AJAX). - Different Entry Points: If
evf-entriesdoesn't trigger it, try the individual entry view:wp-admin/admin.php?page=evf-entries&view=view-entry&entry_id=<entry_id>. - Gadget Chains: If
GuzzleHttpisn't present, check forRequests(WordPress core) or other common libraries used by Everest Forms.
Summary
The Everest Forms plugin for WordPress (versions <= 3.4.3) is vulnerable to unauthenticated PHP Object Injection due to improper use of the native PHP unserialize() function on form entry metadata. Attackers can submit malicious serialized objects through form fields, which are stored in the database and executed when an administrator views the submissions in the dashboard.
Vulnerable Code
// includes/admin/views/html-admin-page-entries-view.php // The code retrieves entry meta and attempts to deserialize it without class restrictions: $entry_meta = $wpdb->get_results( ... ); foreach ( $entry_meta as $meta_value ) { // ... $meta_val = unserialize( $meta_value->meta_value ); // ... }
Security Fix
@@ -124,7 +124,7 @@ if ( is_serialized( $meta_value->meta_value ) ) { - $meta_val = unserialize( $meta_value->meta_value ); + $meta_val = unserialize( $meta_value->meta_value, array( 'allowed_classes' => false ) ); if ( is_array( $meta_val ) ) {
Exploit Outline
1. Access a public page containing an Everest Forms form and extract the submission nonce from 'window.evf_frontend_params'. 2. Construct a PHP Object Injection payload using an available POP gadget chain. 3. Send an unauthenticated POST request to '/wp-admin/admin-ajax.php' with the 'action' set to 'everest_forms_submit_form' and the malicious payload in a form field parameter. 4. The payload is stored in the 'wp_evf_entrymeta' table as part of the submission metadata. 5. Trigger the payload by having an administrator visit the 'Entries' management page ('wp-admin/admin.php?page=evf-entries') in the WordPress backend, where the plugin insecurely deserializes the stored value.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.