Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/finger/finger_users.rb
19823 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Auxiliary
7
include Msf::Exploit::Remote::Tcp
8
include Msf::Auxiliary::Scanner
9
include Msf::Auxiliary::Report
10
11
def initialize
12
super(
13
'Name' => 'Finger Service User Enumerator',
14
'Description' => 'Identify valid users through the finger service using a variety of tricks',
15
'Author' => 'hdm',
16
'License' => MSF_LICENSE
17
)
18
register_options([
19
Opt::RPORT(79),
20
OptString.new('USERS_FILE',
21
[
22
true, 'The file that contains a list of default UNIX accounts.',
23
File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_users.txt')
24
])
25
])
26
end
27
28
def run_host(ip)
29
@users = {}
30
31
begin
32
vprint_status "#{rhost}:#{rport} - Sending empty finger request."
33
finger_empty
34
vprint_status "#{rhost}:#{rport} - Sending test finger requests."
35
finger_zero
36
finger_dot
37
finger_chars
38
vprint_status "#{rhost}:#{rport} - Sending finger request for #{finger_user_common.count} users"
39
finger_list
40
rescue ::Rex::ConnectionError
41
rescue ::Exception => e
42
print_error("#{e} #{e.backtrace}")
43
end
44
report_service(:host => rhost, :port => rport, :name => "finger")
45
46
if (@users.empty?)
47
print_status("#{ip}:#{rport} No users found.")
48
else
49
print_good("#{ip}:#{rport} Users found: #{@users.keys.sort.join(", ")}")
50
report_note(
51
:host => rhost,
52
:port => rport,
53
:type => 'finger.users',
54
:data => { :users => @users.keys }
55
)
56
end
57
end
58
59
def finger_empty
60
connect
61
sock.put("\r\n")
62
buff = finger_slurp_data
63
parse_users(buff)
64
disconnect
65
end
66
67
def finger_zero
68
connect
69
sock.put("0\r\n")
70
buff = finger_slurp_data
71
parse_users(buff)
72
disconnect
73
end
74
75
def finger_dot
76
connect
77
sock.put(".\r\n")
78
buff = finger_slurp_data
79
parse_users(buff)
80
disconnect
81
end
82
83
def finger_chars
84
connect
85
sock.put("m m m m m m m m\r\n")
86
buff = finger_slurp_data
87
if buff.scan(/\r?\nm\s/).size > 7
88
@multiple_requests = true
89
vprint_status "#{rhost}:#{rport} - Multiple users per request is okay."
90
end
91
parse_users(buff)
92
disconnect
93
end
94
95
def finger_list
96
if !@multiple_requests
97
finger_user_common.each do |user|
98
next if @users[user]
99
100
connect
101
vprint_status "#{rhost}:#{rport} - Sending finger request for #{user}..."
102
sock.put("#{user}\r\n")
103
buff = finger_slurp_data
104
ret = parse_users(buff)
105
disconnect
106
break if not ret
107
end
108
else
109
while !finger_user_common.empty?
110
user_batch = []
111
while user_batch.size < 8 and !finger_user_common.empty?
112
new_user = finger_user_common.shift
113
next if @users.keys.include? new_user
114
115
user_batch << new_user
116
end
117
connect
118
vprint_status "#{rhost}:#{rport} - Sending finger request for #{user_batch.join(", ")}..."
119
sock.put("#{user_batch.join(" ")}\r\n")
120
buff = finger_slurp_data
121
ret = parse_users(buff)
122
disconnect
123
break if not ret
124
end
125
end
126
end
127
128
def finger_slurp_data
129
buff = ""
130
begin
131
while (res = sock.get_once(-1, 5) || '')
132
buff << res
133
break if buff.length > (1024 * 1024)
134
end
135
rescue ::Interrupt
136
raise $!
137
rescue ::Exception
138
end
139
buff
140
end
141
142
def finger_user_common
143
if (!@common)
144
File.open(datastore['USERS_FILE'], "rb") do |fd|
145
data = fd.read(fd.stat.size)
146
@common = data.split(/\n/).compact.uniq
147
@common.delete("")
148
end
149
end
150
@common
151
end
152
153
def parse_users(buff)
154
buff.each_line do |line|
155
uid = nil
156
next if line.strip.empty?
157
158
# Ignore Cisco systems
159
return if line =~ /Line.*User.*Host.*Location/
160
161
next if line =~ /user not found/i
162
next if line =~ /no such user/i
163
next if line =~ /must provide username/
164
next if line =~ /real life: \?\?\?/
165
next if line =~ /No one logged on/
166
next if line =~ /^Login\s+Name\s+TTY/
167
168
# print_status(">> #{line}")
169
170
# No such file or directory == valid user bad utmp
171
172
case line
173
when /^([a-z0-9\.\_]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)/
174
# Solaris
175
uid = $1
176
if ($2 != "Name")
177
@users[uid] ||= {}
178
end
179
180
when /^\s*Login name:\s*([^\s]+)\s+/i
181
# IRIX
182
uid = $1
183
@users[uid] ||= {} if uid
184
when /^\s*(?:Username|Login):\s*([^\s]+)\s+/i
185
# Debian GNU/Linux
186
uid = $1
187
@users[uid] ||= {} if uid
188
end
189
190
if uid
191
print_good "#{rhost}:#{rport} - Found user: #{uid}" unless @users[uid] == :reported
192
@users[uid] = :reported
193
next
194
end
195
end
196
return true
197
end
198
end
199
200