CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/finger/finger_users.rb
Views: 1904
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
[ true, 'The file that contains a list of default UNIX accounts.',
22
File.join(Msf::Config.install_root, 'data', 'wordlists', 'unix_users.txt')
23
]
24
)])
25
end
26
27
def run_host(ip)
28
@users = {}
29
30
begin
31
vprint_status "#{rhost}:#{rport} - Sending empty finger request."
32
finger_empty
33
vprint_status "#{rhost}:#{rport} - Sending test finger requests."
34
finger_zero
35
finger_dot
36
finger_chars
37
vprint_status "#{rhost}:#{rport} - Sending finger request for #{finger_user_common.count} users"
38
finger_list
39
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
60
def finger_empty
61
connect
62
sock.put("\r\n")
63
buff = finger_slurp_data
64
parse_users(buff)
65
disconnect
66
end
67
68
def finger_zero
69
connect
70
sock.put("0\r\n")
71
buff = finger_slurp_data
72
parse_users(buff)
73
disconnect
74
end
75
76
def finger_dot
77
connect
78
sock.put(".\r\n")
79
buff = finger_slurp_data
80
parse_users(buff)
81
disconnect
82
end
83
84
def finger_chars
85
connect
86
sock.put("m m m m m m m m\r\n")
87
buff = finger_slurp_data
88
if buff.scan(/\r?\nm\s/).size > 7
89
@multiple_requests = true
90
vprint_status "#{rhost}:#{rport} - Multiple users per request is okay."
91
end
92
parse_users(buff)
93
disconnect
94
end
95
96
def finger_list
97
if !@multiple_requests
98
finger_user_common.each do |user|
99
next if @users[user]
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
user_batch << new_user
115
end
116
connect
117
vprint_status "#{rhost}:#{rport} - Sending finger request for #{user_batch.join(", ")}..."
118
sock.put("#{user_batch.join(" ")}\r\n")
119
buff = finger_slurp_data
120
ret = parse_users(buff)
121
disconnect
122
break if not ret
123
end
124
end
125
end
126
127
def finger_slurp_data
128
buff = ""
129
begin
130
while(res = sock.get_once(-1, 5) || '')
131
buff << res
132
break if buff.length > (1024*1024)
133
end
134
rescue ::Interrupt
135
raise $!
136
rescue ::Exception
137
end
138
buff
139
end
140
141
def finger_user_common
142
if(! @common)
143
File.open(datastore['USERS_FILE'], "rb") do |fd|
144
data = fd.read(fd.stat.size)
145
@common = data.split(/\n/).compact.uniq
146
@common.delete("")
147
end
148
end
149
@common
150
end
151
152
def parse_users(buff)
153
buff.each_line do |line|
154
uid = nil
155
next if line.strip.empty?
156
157
# Ignore Cisco systems
158
return if line =~ /Line.*User.*Host.*Location/
159
160
next if line =~ /user not found/i
161
next if line =~ /no such user/i
162
next if line =~ /must provide username/
163
next if line =~ /real life: \?\?\?/
164
next if line =~ /No one logged on/
165
next if line =~ /^Login\s+Name\s+TTY/
166
167
# print_status(">> #{line}")
168
169
# No such file or directory == valid user bad utmp
170
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