Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

telnet.rb 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. # -*- coding: binary -*-
  2. module Msf
  3. require 'msf/core/exploit/tcp'
  4. ###
  5. #
  6. # This module exposes methods that may be useful to exploits that deal with
  7. # servers that speak the telnet protocol.
  8. #
  9. ###
  10. module Exploit::Remote::Telnet
  11. include Exploit::Remote::Tcp
  12. include Auxiliary::Login
  13. # Borrowing constants from Ruby's Net::Telnet class (ruby license)
  14. IAC = 255.chr # "\377" # "\xff" # interpret as command
  15. DONT = 254.chr # "\376" # "\xfe" # you are not to use option
  16. DO = 253.chr # "\375" # "\xfd" # please, you use option
  17. WONT = 252.chr # "\374" # "\xfc" # I won't use option
  18. WILL = 251.chr # "\373" # "\xfb" # I will use option
  19. SB = 250.chr # "\372" # "\xfa" # interpret as subnegotiation
  20. GA = 249.chr # "\371" # "\xf9" # you may reverse the line
  21. EL = 248.chr # "\370" # "\xf8" # erase the current line
  22. EC = 247.chr # "\367" # "\xf7" # erase the current character
  23. AYT = 246.chr # "\366" # "\xf6" # are you there
  24. AO = 245.chr # "\365" # "\xf5" # abort output--but let prog finish
  25. IP = 244.chr # "\364" # "\xf4" # interrupt process--permanently
  26. BREAK = 243.chr # "\363" # "\xf3" # break
  27. DM = 242.chr # "\362" # "\xf2" # data mark--for connect. cleaning
  28. NOP = 241.chr # "\361" # "\xf1" # nop
  29. SE = 240.chr # "\360" # "\xf0" # end sub negotiation
  30. EOR = 239.chr # "\357" # "\xef" # end of record (transparent mode)
  31. ABORT = 238.chr # "\356" # "\xee" # Abort process
  32. SUSP = 237.chr # "\355" # "\xed" # Suspend process
  33. EOF = 236.chr # "\354" # "\xec" # End of file
  34. SYNCH = 242.chr # "\362" # "\xf2" # for telfunc calls
  35. OPT_BINARY = 0.chr # "\000" # "\x00" # Binary Transmission
  36. OPT_ECHO = 1.chr # "\001" # "\x01" # Echo
  37. OPT_RCP = 2.chr # "\002" # "\x02" # Reconnection
  38. OPT_SGA = 3.chr # "\003" # "\x03" # Suppress Go Ahead
  39. OPT_NAMS = 4.chr # "\004" # "\x04" # Approx Message Size Negotiation
  40. OPT_STATUS = 5.chr # "\005" # "\x05" # Status
  41. OPT_TM = 6.chr # "\006" # "\x06" # Timing Mark
  42. OPT_RCTE = 7.chr # "\a" # "\x07" # Remote Controlled Trans and Echo
  43. OPT_NAOL = 8.chr # "\010" # "\x08" # Output Line Width
  44. OPT_NAOP = 9.chr # "\t" # "\x09" # Output Page Size
  45. OPT_NAOCRD = 10.chr # "\n" # "\x0a" # Output Carriage-Return Disposition
  46. OPT_NAOHTS = 11.chr # "\v" # "\x0b" # Output Horizontal Tab Stops
  47. OPT_NAOHTD = 12.chr # "\f" # "\x0c" # Output Horizontal Tab Disposition
  48. OPT_NAOFFD = 13.chr # "\r" # "\x0d" # Output Formfeed Disposition
  49. OPT_NAOVTS = 14.chr # "\016" # "\x0e" # Output Vertical Tabstops
  50. OPT_NAOVTD = 15.chr # "\017" # "\x0f" # Output Vertical Tab Disposition
  51. OPT_NAOLFD = 16.chr # "\020" # "\x10" # Output Linefeed Disposition
  52. OPT_XASCII = 17.chr # "\021" # "\x11" # Extended ASCII
  53. OPT_LOGOUT = 18.chr # "\022" # "\x12" # Logout
  54. OPT_BM = 19.chr # "\023" # "\x13" # Byte Macro
  55. OPT_DET = 20.chr # "\024" # "\x14" # Data Entry Terminal
  56. OPT_SUPDUP = 21.chr # "\025" # "\x15" # SUPDUP
  57. OPT_SUPDUPOUTPUT = 22.chr # "\026" # "\x16" # SUPDUP Output
  58. OPT_SNDLOC = 23.chr # "\027" # "\x17" # Send Location
  59. OPT_TTYPE = 24.chr # "\030" # "\x18" # Terminal Type
  60. OPT_EOR = 25.chr # "\031" # "\x19" # End of Record
  61. OPT_TUID = 26.chr # "\032" # "\x1a" # TACACS User Identification
  62. OPT_OUTMRK = 27.chr # "\e" # "\x1b" # Output Marking
  63. OPT_TTYLOC = 28.chr # "\034" # "\x1c" # Terminal Location Number
  64. OPT_3270REGIME = 29.chr # "\035" # "\x1d" # Telnet 3270 Regime
  65. OPT_X3PAD = 30.chr # "\036" # "\x1e" # X.3 PAD
  66. OPT_NAWS = 31.chr # "\037" # "\x1f" # Negotiate About Window Size
  67. OPT_TSPEED = 32.chr # " " # "\x20" # Terminal Speed
  68. OPT_LFLOW = 33.chr # "!" # "\x21" # Remote Flow Control
  69. OPT_LINEMODE = 34.chr # "\"" # "\x22" # Linemode
  70. OPT_XDISPLOC = 35.chr # "#" # "\x23" # X Display Location
  71. OPT_OLD_ENVIRON = 36.chr # "$" # "\x24" # Environment Option
  72. OPT_AUTHENTICATION = 37.chr # "%" # "\x25" # Authentication Option
  73. OPT_ENCRYPT = 38.chr # "&" # "\x26" # Encryption Option
  74. OPT_NEW_ENVIRON = 39.chr # "'" # "\x27" # New Environment Option
  75. OPT_EXOPL = 255.chr # "\377" # "\xff" # Extended-Options-List
  76. #
  77. # Creates an instance of a Telnet exploit module.
  78. #
  79. def initialize(info = {})
  80. super
  81. # Register the options that all Telnet exploits may make use of.
  82. register_options(
  83. [
  84. Opt::RHOST,
  85. Opt::RPORT(23),
  86. OptString.new('USERNAME', [ false, 'The username to authenticate as' ]),
  87. OptString.new('PASSWORD', [ false, 'The password for the specified username' ])
  88. ], Msf::Exploit::Remote::Telnet)
  89. register_advanced_options(
  90. [
  91. OptInt.new('TelnetTimeout', [ true, 'The number of seconds to wait for a reply from a Telnet command', 10]),
  92. OptInt.new('TelnetBannerTimeout', [ true, 'The number of seconds to wait for the initial banner', 25])
  93. ], Msf::Exploit::Remote::Telnet)
  94. register_autofilter_ports([ 23 ])
  95. register_autofilter_services(%W{ telnet })
  96. end
  97. #
  98. # This method establishes an Telnet connection to host and port specified by
  99. # the RHOST and RPORT options, respectively. After connecting, the banner
  100. # message is read in and stored in the 'banner' attribute. This method has the
  101. # benefit of handling telnet option negotiation.
  102. #
  103. def connect(global = true, verbose = true)
  104. @trace = ''
  105. @recvd = ''
  106. fd = super(global)
  107. banner_timeout = (datastore['TelnetBannerTimeout'] || 25).to_i
  108. self.banner = ''
  109. # Wait for a banner to arrive...
  110. begin
  111. Timeout.timeout(banner_timeout) do
  112. while(true)
  113. buff = recv(fd)
  114. self.banner << buff if buff
  115. if(self.banner =~ @login_regex or self.banner =~ @password_regex)
  116. break
  117. elsif self.banner =~ @busy_regex
  118. # It's about to drop connection anyway -- seen on HP JetDirect telnet server
  119. break
  120. end
  121. end
  122. end
  123. rescue ::Timeout::Error
  124. end
  125. self.banner.strip!
  126. # Return the file descriptor to the caller
  127. fd
  128. end
  129. def recv(fd=self.sock, timeout=datastore['TelnetTimeout'])
  130. recv_telnet(fd, timeout.to_f)
  131. end
  132. #
  133. # Handle telnet option negotiation
  134. #
  135. # Appends to the @recvd buffer which is used to tell us whether we're at a
  136. # login prompt, a password prompt, or a working shell.
  137. #
  138. def recv_telnet(fd, timeout)
  139. data = ''
  140. begin
  141. data = fd.get_once(-1, timeout)
  142. return nil if not data or data.length == 0
  143. # combine CR+NULL into CR
  144. data.gsub!(/#{CR}#{NULL}/no, CR)
  145. # combine EOL into "\n"
  146. data.gsub!(/#{EOL}/no, "\n")
  147. data.gsub!(/#{IAC}(
  148. [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]|[#{DO}#{DONT}#{WILL}#{WONT}]
  149. [#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]|#{SB}[^#{IAC}]*#{IAC}#{SE}
  150. )/xno) do
  151. m = $1
  152. if m == IAC
  153. IAC
  154. elsif m == AYT
  155. fd.write("YES" + EOL)
  156. ''
  157. elsif m[0,1] == DO
  158. if(m[1,1] == OPT_BINARY)
  159. fd.write(IAC + WILL + OPT_BINARY)
  160. else
  161. fd.write(IAC + WONT + m[1,1])
  162. end
  163. ''
  164. elsif m[0,1] == DONT
  165. fd.write(IAC + WONT + m[1,1])
  166. ''
  167. elsif m[0,1] == WILL
  168. if m[1,1] == OPT_BINARY
  169. fd.write(IAC + DO + OPT_BINARY)
  170. # Disable Echo
  171. elsif m[1,1] == OPT_ECHO
  172. fd.write(IAC + DONT + OPT_ECHO)
  173. elsif m[1,1] == OPT_SGA
  174. fd.write(IAC + DO + OPT_SGA)
  175. else
  176. fd.write(IAC + DONT + m[1,1])
  177. end
  178. ''
  179. elsif m[0,1] == WONT
  180. fd.write(IAC + DONT + m[1,1])
  181. ''
  182. else
  183. ''
  184. end
  185. end
  186. @trace << data
  187. @recvd << data
  188. fd.flush
  189. rescue ::EOFError, ::Errno::EPIPE
  190. end
  191. data
  192. end
  193. def user
  194. datastore["USERNAME"]
  195. end
  196. def pass
  197. datastore["PASSWORD"]
  198. end
  199. ##
  200. #
  201. # Wrappers for getters
  202. #
  203. ##
  204. #
  205. # Returns the number of seconds to wait for a telnet reply
  206. #
  207. def tel_timeout
  208. (datastore['TelnetTimeout'] || 10).to_i
  209. end
  210. protected
  211. #
  212. # This attribute holds the banner that was read in after a successful call
  213. # to connect or connect_login.
  214. #
  215. attr_accessor :banner
  216. end
  217. end