Path: blob/master/modules/auxiliary/scanner/finger/finger_users.rb
19823 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::Tcp7include Msf::Auxiliary::Scanner8include Msf::Auxiliary::Report910def initialize11super(12'Name' => 'Finger Service User Enumerator',13'Description' => 'Identify valid users through the finger service using a variety of tricks',14'Author' => 'hdm',15'License' => MSF_LICENSE16)17register_options([18Opt::RPORT(79),19OptString.new('USERS_FILE',20[21true, 'The file that contains a list of default UNIX accounts.',22File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_users.txt')23])24])25end2627def run_host(ip)28@users = {}2930begin31vprint_status "#{rhost}:#{rport} - Sending empty finger request."32finger_empty33vprint_status "#{rhost}:#{rport} - Sending test finger requests."34finger_zero35finger_dot36finger_chars37vprint_status "#{rhost}:#{rport} - Sending finger request for #{finger_user_common.count} users"38finger_list39rescue ::Rex::ConnectionError40rescue ::Exception => e41print_error("#{e} #{e.backtrace}")42end43report_service(:host => rhost, :port => rport, :name => "finger")4445if (@users.empty?)46print_status("#{ip}:#{rport} No users found.")47else48print_good("#{ip}:#{rport} Users found: #{@users.keys.sort.join(", ")}")49report_note(50:host => rhost,51:port => rport,52:type => 'finger.users',53:data => { :users => @users.keys }54)55end56end5758def finger_empty59connect60sock.put("\r\n")61buff = finger_slurp_data62parse_users(buff)63disconnect64end6566def finger_zero67connect68sock.put("0\r\n")69buff = finger_slurp_data70parse_users(buff)71disconnect72end7374def finger_dot75connect76sock.put(".\r\n")77buff = finger_slurp_data78parse_users(buff)79disconnect80end8182def finger_chars83connect84sock.put("m m m m m m m m\r\n")85buff = finger_slurp_data86if buff.scan(/\r?\nm\s/).size > 787@multiple_requests = true88vprint_status "#{rhost}:#{rport} - Multiple users per request is okay."89end90parse_users(buff)91disconnect92end9394def finger_list95if !@multiple_requests96finger_user_common.each do |user|97next if @users[user]9899connect100vprint_status "#{rhost}:#{rport} - Sending finger request for #{user}..."101sock.put("#{user}\r\n")102buff = finger_slurp_data103ret = parse_users(buff)104disconnect105break if not ret106end107else108while !finger_user_common.empty?109user_batch = []110while user_batch.size < 8 and !finger_user_common.empty?111new_user = finger_user_common.shift112next if @users.keys.include? new_user113114user_batch << new_user115end116connect117vprint_status "#{rhost}:#{rport} - Sending finger request for #{user_batch.join(", ")}..."118sock.put("#{user_batch.join(" ")}\r\n")119buff = finger_slurp_data120ret = parse_users(buff)121disconnect122break if not ret123end124end125end126127def finger_slurp_data128buff = ""129begin130while (res = sock.get_once(-1, 5) || '')131buff << res132break if buff.length > (1024 * 1024)133end134rescue ::Interrupt135raise $!136rescue ::Exception137end138buff139end140141def finger_user_common142if (!@common)143File.open(datastore['USERS_FILE'], "rb") do |fd|144data = fd.read(fd.stat.size)145@common = data.split(/\n/).compact.uniq146@common.delete("")147end148end149@common150end151152def parse_users(buff)153buff.each_line do |line|154uid = nil155next if line.strip.empty?156157# Ignore Cisco systems158return if line =~ /Line.*User.*Host.*Location/159160next if line =~ /user not found/i161next if line =~ /no such user/i162next if line =~ /must provide username/163next if line =~ /real life: \?\?\?/164next if line =~ /No one logged on/165next if line =~ /^Login\s+Name\s+TTY/166167# print_status(">> #{line}")168169# No such file or directory == valid user bad utmp170171case line172when /^([a-z0-9\.\_]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/173# Solaris174uid = $1175if ($2 != "Name")176@users[uid] ||= {}177end178179when /^\s*Login name:\s*([^\s]+)\s+/i180# IRIX181uid = $1182@users[uid] ||= {} if uid183when /^\s*(?:Username|Login):\s*([^\s]+)\s+/i184# Debian GNU/Linux185uid = $1186@users[uid] ||= {} if uid187end188189if uid190print_good "#{rhost}:#{rport} - Found user: #{uid}" unless @users[uid] == :reported191@users[uid] = :reported192next193end194end195return true196end197end198199200