Lucene search
+L

Finger Service User Enumerator

🗓️ 15 Jan 2010 02:58:59Reported by hdm <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 14 Views

Finger Service User Enumerator, Identify valid users through the finger service using a variety of trick

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::Scanner
  include Msf::Auxiliary::Report

  def initialize
    super(
      'Name'        => 'Finger Service User Enumerator',
      'Description' => 'Identify valid users through the finger service using a variety of tricks',
      'Author'      => 'hdm',
      'License'     => MSF_LICENSE
    )
    register_options([
      Opt::RPORT(79),
      OptString.new('USERS_FILE',
        [ true, 'The file that contains a list of default UNIX accounts.',
          File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_users.txt')
        ]
      )])
  end

  def run_host(ip)
    @users = {}

    begin
      vprint_status "#{rhost}:#{rport} - Sending empty finger request."
      finger_empty
      vprint_status "#{rhost}:#{rport} - Sending test finger requests."
      finger_zero
      finger_dot
      finger_chars
      vprint_status "#{rhost}:#{rport} - Sending finger request for #{finger_user_common.count} users"
      finger_list

    rescue ::Rex::ConnectionError
    rescue ::Exception => e
      print_error("#{e} #{e.backtrace}")
    end
    report_service(:host => rhost, :port => rport, :name => "finger")

    if(@users.empty?)
      print_status("#{ip}:#{rport} No users found.")
    else
      print_good("#{ip}:#{rport} Users found: #{@users.keys.sort.join(", ")}")
      report_note(
        :host => rhost,
        :port => rport,
        :type => 'finger.users',
        :data => {:users => @users.keys}
      )
    end
  end


  def finger_empty
    connect
    sock.put("\r\n")
    buff = finger_slurp_data
    parse_users(buff)
    disconnect
  end

  def finger_zero
    connect
    sock.put("0\r\n")
    buff = finger_slurp_data
    parse_users(buff)
    disconnect
  end

  def finger_dot
    connect
    sock.put(".\r\n")
    buff = finger_slurp_data
    parse_users(buff)
    disconnect
  end

  def finger_chars
    connect
    sock.put("m m m m m m m m\r\n")
    buff = finger_slurp_data
    if buff.scan(/\r?\nm\s/).size > 7
      @multiple_requests = true
      vprint_status "#{rhost}:#{rport} - Multiple users per request is okay."
    end
    parse_users(buff)
    disconnect
  end

  def finger_list
    if !@multiple_requests
      finger_user_common.each do |user|
        next if @users[user]
        connect
        vprint_status "#{rhost}:#{rport} - Sending finger request for #{user}..."
        sock.put("#{user}\r\n")
        buff = finger_slurp_data
        ret = parse_users(buff)
        disconnect
        break if not ret
      end
    else
      while !finger_user_common.empty?
        user_batch = []
        while user_batch.size < 8 and !finger_user_common.empty?
          new_user = finger_user_common.shift
          next if @users.keys.include? new_user
          user_batch << new_user
        end
        connect
        vprint_status "#{rhost}:#{rport} - Sending finger request for #{user_batch.join(", ")}..."
        sock.put("#{user_batch.join(" ")}\r\n")
        buff = finger_slurp_data
        ret = parse_users(buff)
        disconnect
        break if not ret
      end
    end
  end

  def finger_slurp_data
    buff = ""
    begin
      while(res = sock.get_once(-1, 5) || '')
        buff << res
        break if buff.length > (1024*1024)
      end
    rescue ::Interrupt
      raise $!
    rescue ::Exception
    end
    buff
  end

  def finger_user_common
    if(! @common)
      File.open(datastore['USERS_FILE'], "rb") do |fd|
        data = fd.read(fd.stat.size)
        @common = data.split(/\n/).compact.uniq
        @common.delete("")
      end
    end
    @common
  end

  def parse_users(buff)
    buff.each_line do |line|
      uid = nil
      next if line.strip.empty?

      # Ignore Cisco systems
      return if line =~ /Line.*User.*Host.*Location/

      next if line =~ /user not found/i
      next if line =~ /no such user/i
      next if line =~ /must provide username/
      next if line =~ /real life: \?\?\?/
      next if line =~ /No one logged on/
      next if line =~ /^Login\s+Name\s+TTY/

      # print_status(">> #{line}")

      # No such file or directory == valid user bad utmp


      case line
      when /^([a-z0-9\.\_]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/
        # Solaris
        uid = $1
        if ($2 != "Name")
          @users[uid] ||= {}
        end

      when /^\s*Login name:\s*([^\s]+)\s+/i
        # IRIX
        uid = $1
        @users[uid] ||= {} if uid
      when /^\s*(?:Username|Login):\s*([^\s]+)\s+/i
        # Debian GNU/Linux
        uid = $1
        @users[uid] ||= {} if uid
      end

      if uid
        print_good "#{rhost}:#{rport} - Found user: #{uid}" unless @users[uid] == :reported
        @users[uid] = :reported
        next
      end
    end
    return true
  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