Module: Msf::Exploit::Remote::Telnet

Includes:
Auxiliary::Login, Tcp
Defined in:
lib/msf/core/exploit/telnet.rb

Overview

This module exposes methods that may be useful to exploits that deal with servers that speak the telnet protocol.

Constant Summary collapse

IAC =

Borrowing constants from Ruby's Net::Telnet class (ruby license)

255.chr
DONT =
254.chr
DO =
253.chr
WONT =
252.chr
WILL =
251.chr
SB =
250.chr
GA =
249.chr
EL =
248.chr
EC =
247.chr
AYT =
246.chr
AO =
245.chr
IP =
244.chr
BREAK =
243.chr
DM =
242.chr
NOP =
241.chr
SE =
240.chr
EOR =
239.chr
ABORT =
238.chr
SUSP =
237.chr
EOF =
236.chr
SYNCH =

“377” # “xff” # interpret as command “376” # “xfe” # you are not to use option “375” # “xfd” # please, you use option “374” # “xfc” # I won't use option “373” # “xfb” # I will use option “372” # “xfa” # interpret as subnegotiation “371” # “xf9” # you may reverse the line “370” # “xf8” # erase the current line “367” # “xf7” # erase the current character “366” # “xf6” # are you there “365” # “xf5” # abort output–but let prog finish “364” # “xf4” # interrupt process–permanently “363” # “xf3” # break “362” # “xf2” # data mark–for connect. cleaning “361” # “xf1” # nop “360” # “xf0” # end sub negotiation “357” # “xef” # end of record (transparent mode) “356” # “xee” # Abort process “355” # “xed” # Suspend process “354” # “xec” # End of file “362” # “xf2” # for telfunc calls

242.chr
OPT_BINARY =
0.chr
OPT_ECHO =
1.chr
OPT_RCP =
2.chr
OPT_SGA =
3.chr
OPT_NAMS =
4.chr
OPT_STATUS =
5.chr
OPT_TM =
6.chr
OPT_RCTE =
7.chr
OPT_NAOL =
8.chr
OPT_NAOP =
9.chr
OPT_NAOCRD =
10.chr
OPT_NAOHTS =
11.chr
OPT_NAOHTD =
12.chr
OPT_NAOFFD =
13.chr
OPT_NAOVTS =
14.chr
OPT_NAOVTD =
15.chr
OPT_NAOLFD =
16.chr
OPT_XASCII =
17.chr
OPT_LOGOUT =
18.chr
OPT_BM =
19.chr
OPT_DET =
20.chr
OPT_SUPDUP =
21.chr
OPT_SUPDUPOUTPUT =
22.chr
OPT_SNDLOC =
23.chr
OPT_TTYPE =
24.chr
OPT_EOR =
25.chr
OPT_TUID =
26.chr
OPT_OUTMRK =
27.chr
OPT_TTYLOC =
28.chr
OPT_3270REGIME =
29.chr
OPT_X3PAD =
30.chr
OPT_NAWS =
31.chr
OPT_TSPEED =
32.chr
OPT_LFLOW =
33.chr
OPT_LINEMODE =
34.chr
OPT_XDISPLOC =
35.chr
OPT_OLD_ENVIRON =
36.chr
OPT_AUTHENTICATION =
37.chr
OPT_ENCRYPT =
38.chr
OPT_NEW_ENVIRON =
39.chr
OPT_EXOPL =

“000” # “x00” # Binary Transmission “001” # “x01” # Echo “002” # “x02” # Reconnection “003” # “x03” # Suppress Go Ahead “004” # “x04” # Approx Message Size Negotiation “005” # “x05” # Status “006” # “x06” # Timing Mark “a” # “x07” # Remote Controlled Trans and Echo “010” # “x08” # Output Line Width “t” # “x09” # Output Page Size “n” # “x0a” # Output Carriage-Return Disposition “v” # “x0b” # Output Horizontal Tab Stops “f” # “x0c” # Output Horizontal Tab Disposition “r” # “x0d” # Output Formfeed Disposition “016” # “x0e” # Output Vertical Tabstops “017” # “x0f” # Output Vertical Tab Disposition “020” # “x10” # Output Linefeed Disposition “021” # “x11” # Extended ASCII “022” # “x12” # Logout “023” # “x13” # Byte Macro “024” # “x14” # Data Entry Terminal “025” # “x15” # SUPDUP “026” # “x16” # SUPDUP Output “027” # “x17” # Send Location “030” # “x18” # Terminal Type “031” # “x19” # End of Record “032” # “x1a” # TACACS User Identification “e” # “x1b” # Output Marking “034” # “x1c” # Terminal Location Number “035” # “x1d” # Telnet 3270 Regime “036” # “x1e” # X.3 PAD “037” # “x1f” # Negotiate About Window Size “ ” # “x20” # Terminal Speed “!” # “x21” # Remote Flow Control “"” # “x22” # Linemode “#” # “x23” # X Display Location “$” # “x24” # Environment Option “%” # “x25” # Authentication Option “&” # “x26” # Encryption Option “'” # “x27” # New Environment Option “377” # “xff” # Extended-Options-List

255.chr

Constants included from Auxiliary::Login

Auxiliary::Login::CR, Auxiliary::Login::EOL, Auxiliary::Login::LF, Auxiliary::Login::NULL

Instance Method Summary collapse

Methods included from Auxiliary::Login

#busy_message?, #command_echo?, #login_failed?, #login_prompt?, #login_succeeded?, #password_prompt?, #raw_send, #recv_all, #send_pass, #send_recv, #send_user, #wait_for, #waiting_message?

Methods included from Tcp

#chost, #cleanup, #connect_timeout, #cport, #disconnect, #handler, #lhost, #lport, #proxies, #rhost, #rport, #set_tcp_evasions, #ssl, #ssl_version

Instance Method Details

#connect(global = true, verbose = true) ⇒ Object

This method establishes an Telnet connection to host and port specified by the RHOST and RPORT options, respectively. After connecting, the banner message is read in and stored in the 'banner' attribute. This method has the benefit of handling telnet option negotiation.


115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/msf/core/exploit/telnet.rb', line 115

def connect(global = true, verbose = true)
  @trace = ''
  @recvd = ''
  fd = super(global)
  banner_timeout = (datastore['TelnetBannerTimeout'] || 25).to_i

  self.banner = ''
  # Wait for a banner to arrive...
  begin
  Timeout.timeout(banner_timeout) do
    while(true)
      buff = recv(fd)
      self.banner << buff if buff
      if(self.banner =~ @login_regex or self.banner =~ @password_regex)
        break
      elsif self.banner =~ @busy_regex
        # It's about to drop connection anyway -- seen on HP JetDirect telnet server
        break
      end
    end
  end
  rescue ::Timeout::Error
  end

  self.banner.strip!

  # Return the file descriptor to the caller
  fd
end

#initialize(info = {}) ⇒ Object

Creates an instance of a Telnet exploit module.


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/msf/core/exploit/telnet.rb', line 87

def initialize(info = {})
  super

  # Register the options that all Telnet exploits may make use of.
  register_options(
    [
      Opt::RHOST,
      Opt::RPORT(23),
      OptString.new('USERNAME', [ false, 'The username to authenticate as' ]),
      OptString.new('PASSWORD', [ false, 'The password for the specified username' ])
    ], Msf::Exploit::Remote::Telnet)

  register_advanced_options(
    [
      OptInt.new('TelnetTimeout', [ true, 'The number of seconds to wait for a reply from a Telnet command', 10]),
      OptInt.new('TelnetBannerTimeout', [ true, 'The number of seconds to wait for the initial banner', 25])
    ], Msf::Exploit::Remote::Telnet)

  register_autofilter_ports([ 23 ])
  register_autofilter_services(%W{ telnet })
end

#passObject


225
226
227
# File 'lib/msf/core/exploit/telnet.rb', line 225

def pass
  datastore["PASSWORD"]
end

#recv(fd = self.sock, timeout = datastore['TelnetTimeout']) ⇒ Object


146
147
148
# File 'lib/msf/core/exploit/telnet.rb', line 146

def recv(fd=self.sock, timeout=datastore['TelnetTimeout'])
  recv_telnet(fd, timeout.to_f)
end

#recv_telnet(fd, timeout) ⇒ Object

Handle telnet option negotiation

Appends to the @recvd buffer which is used to tell us whether we're at a login prompt, a password prompt, or a working shell.


156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/msf/core/exploit/telnet.rb', line 156

def recv_telnet(fd, timeout)

  data = ''

  begin
    data = fd.get_once(-1, timeout)
    return nil if not data or data.length == 0

    # combine CR+NULL into CR
    data.gsub!(/#{CR}#{NULL}/no, CR)

    # combine EOL into "\n"
    data.gsub!(/#{EOL}/no, "\n")

    data.gsub!(/#{IAC}(
        [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]|[#{DO}#{DONT}#{WILL}#{WONT}]
        [#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]|#{SB}[^#{IAC}]*#{IAC}#{SE}
        )/xno) do
      m = $1

      if m == IAC
        IAC
      elsif m == AYT
        fd.write("YES" + EOL)
        ''
      elsif m[0,1] == DO
        if(m[1,1] == OPT_BINARY)
          fd.write(IAC + WILL + OPT_BINARY)
        else
          fd.write(IAC + WONT + m[1,1])
        end
        ''
      elsif m[0,1] == DONT
        fd.write(IAC + WONT + m[1,1])
        ''
      elsif m[0,1] == WILL
        if m[1,1] == OPT_BINARY
          fd.write(IAC + DO + OPT_BINARY)
          # Disable Echo
        elsif m[1,1] == OPT_ECHO
          fd.write(IAC + DONT + OPT_ECHO)
        elsif m[1,1] == OPT_SGA
          fd.write(IAC + DO + OPT_SGA)
        else
          fd.write(IAC + DONT + m[1,1])
        end
        ''
      elsif m[0,1] == WONT
        fd.write(IAC + DONT + m[1,1])
        ''
      else
        ''
      end
    end

    @trace << data
    @recvd << data
    fd.flush

  rescue ::EOFError, ::Errno::EPIPE
  end

  data
end

#tel_timeoutObject

Returns the number of seconds to wait for a telnet reply


238
239
240
# File 'lib/msf/core/exploit/telnet.rb', line 238

def tel_timeout
  (datastore['TelnetTimeout'] || 10).to_i
end

#userObject


221
222
223
# File 'lib/msf/core/exploit/telnet.rb', line 221

def user
  datastore["USERNAME"]
end