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/lib/msf/core/auxiliary/login.rb
Views: 1904
1
# -*- coding: binary -*-
2
3
module Msf
4
5
###
6
#
7
# This module exposes methods that may be useful to exploits that deal with
8
# servers that require authentication via /bin/login
9
#
10
###
11
module Auxiliary::Login
12
13
NULL = "\000"
14
CR = "\r"
15
LF = "\n"
16
EOL = CR + LF
17
18
#
19
# Creates an instance of a login negotiation module.
20
#
21
def initialize(info = {})
22
super
23
24
create_login_ivars
25
end
26
27
def create_login_ivars
28
# Appended to by each read and gets reset after each send. Doing it
29
# this way lets us deal with partial reads in the middle of expect
30
# strings, e.g., the first recv returns "Pa" and the second returns
31
# "ssword: "
32
@recvd = ''
33
@trace = ''
34
35
#
36
# Some of these regexes borrowed from NeXpose, others added from datasets
37
#
38
@login_regex = /(?:log[io]n( name|)|user( ?name|id|))\s*\:/i
39
@password_regex = /(?:password|passwd)\s*\:/i
40
@false_failure_regex = /(?:(^\s*last)\ login *\:|allows only\ .*\ Telnet\ Client\ License)/i
41
@failure_regex = /(?:
42
Incorrect | Unknown | Fail | Invalid |
43
Login | Password | Passwd | Username |
44
Unable | Error | Denied | Reject |
45
Refuse | Close | Closing | %\ Bad |
46
Sorry |
47
^http | html |
48
Not\ on\ system\ console |
49
Enter\ username\ and\ password |
50
Auto\ Apply\ On |
51
YOU\ LOGGED\ IN\ USING\ ALL\ UPPERCASE\ CHARACTERS|
52
\n\*$ |
53
(Login ?|User ?)(name|): |
54
^\s*\<[a-f0-9]+\>\s*$ |
55
^\s*220.*FTP|
56
not\ allowed\ to\ log\ in
57
)/mix
58
59
@waiting_regex = /(?:
60
.*please\ wait.* |
61
.*one\ minute.*
62
)/mix
63
64
@busy_regex = /(?:
65
Another\ telnet\ session\ is\ in\ progress | Disconnecting\.\.\.
66
)/mix
67
68
@success_regex = /(?:
69
list\ of\ built-in |
70
sh.*[\#\$]\s*$ |
71
\[\/\]\s*$ |
72
or\ the\ MENU\ system |
73
Password\ is\ not\ set |
74
logging\ in\ as\ visitor |
75
Login\ successful
76
)/mix
77
end
78
79
#
80
# Appends to the @recvd buffer which is used to tell us whether we're at a
81
# login prompt, a password prompt, or a working shell.
82
#
83
def recv(fd=self.sock, timeout=10)
84
85
data = ''
86
87
begin
88
data = fd.get_once(-1, timeout)
89
return nil if not data or data.length == 0
90
91
# combine EOL into "\n"
92
data.gsub!(/#{EOL}/no, "\n")
93
94
@trace << data
95
@recvd << data
96
fd.flush
97
98
rescue ::EOFError, ::Errno::EPIPE
99
end
100
101
data
102
end
103
104
def login_prompt?
105
return true if @recvd =~ @login_regex
106
return false
107
end
108
109
def command_echo?(cmd)
110
recvn = @recvd.gsub(/^(\s*#{cmd}\r?\n\s*|\s*\*+\s*)/, '')
111
if(recvn != @recvd)
112
@recvd = recvn
113
return true
114
end
115
false
116
end
117
118
def waiting_message?
119
recvn = @recvd.gsub(@waiting_regex, '')
120
if(recvn != @recvd)
121
@recvd = recvn.strip
122
return true
123
end
124
false
125
end
126
127
def busy_message?
128
recvn = @recvd.gsub(@busy_regex, '')
129
if(recvn != @recvd)
130
@recvd = recvn.strip
131
return true
132
end
133
false
134
end
135
136
def password_prompt?(username=nil)
137
return true if(@recvd =~ @password_regex)
138
if username
139
return true if !(username.empty?) and @recvd.to_s.include?("#{username}'s")
140
end
141
return false
142
end
143
144
def login_failed?
145
# Naively, failure means matching the failure regex.
146
#
147
# However, this leads to problems with false positives in the case of
148
# "login:" because unix systems commonly show "Last login: Sat Jan 3
149
# 20:22:52" upon successful login, so check against a false-positive
150
# regex, also.
151
#
152
153
# Empty strings should not count
154
if @recvd.strip.length == 0
155
return true
156
end
157
158
# If we have not seen a newline, this is likely an echo'd prompt
159
if ! @recvd.index("\n")
160
return true
161
end
162
163
# We do have a set of highly-accurate success patterns
164
if (@recvd =~ @success_regex)
165
return false
166
end
167
168
if @recvd =~ @failure_regex
169
if @recvd !~ @false_failure_regex
170
return true
171
end
172
end
173
return false
174
end
175
176
def login_succeeded?
177
# Much easier to test for failure than success because a few key words
178
# mean failure whereas all kinds of crap is used for success, much of
179
# which also shows up in failure messages.
180
return (not login_failed?)
181
end
182
183
#
184
# This method logs in as the supplied user by transmitting the username
185
#
186
def send_user(user, nsock = self.sock)
187
got_prompt = wait_for(@login_regex)
188
if not got_prompt
189
print_error("#{rhost} - Something is wrong, didn't get a login prompt")
190
end
191
return send_recv("#{user}\r\n")
192
end
193
194
#
195
# This method completes user authentication by sending the supplied password
196
#
197
def send_pass(pass, nsock = self.sock)
198
got_prompt = wait_for(@password_regex)
199
if not got_prompt
200
print_error("#{rhost} - Something is wrong, didn't get a password prompt")
201
end
202
return send_recv("#{pass}\r\n")
203
end
204
205
def send_recv(msg, nsock = self.sock)
206
raw_send(msg, nsock)
207
recv_all(nsock)
208
return @recvd
209
end
210
211
def recv_all(nsock = self.sock, timeout = 10)
212
# Make sure we read something in
213
wait_for(/./)
214
end
215
216
#
217
# This method transmits a telnet command and does not wait for a response
218
#
219
# Resets the @recvd buffer
220
#
221
def raw_send(cmd, nsock = self.sock)
222
@recvd = ''
223
@trace << cmd
224
nsock.put(cmd)
225
end
226
227
#
228
# Wait for the supplied string (or Regexp) to show up on the socket, or a
229
# timeout
230
#
231
def wait_for(expect, nsock = self.sock)
232
if expect.kind_of? Regexp
233
regx = expect
234
else
235
regx = /#{Regexp.quote(expect)}/i
236
end
237
return true if @recvd =~ regx
238
239
resp = ''
240
while (resp and not @recvd =~ regx)
241
resp = recv(nsock)
242
end
243
244
return (@recvd =~ regx)
245
end
246
247
end
248
249
end
250
251