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.

server.rb 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. # -*- coding: binary -*-
  2. require 'rex/service_manager'
  3. require 'rex/exploitation/obfuscatejs'
  4. require 'rex/exploitation/encryptjs'
  5. require 'rex/exploitation/heaplib'
  6. require 'rex/exploitation/js'
  7. module Msf
  8. ###
  9. #
  10. # This module provides methods for exploiting an HTTP client by acting
  11. # as an HTTP server.
  12. #
  13. ###
  14. module Exploit::Remote::HttpServer
  15. autoload :HTML, 'msf/core/exploit/http/server/html'
  16. autoload :PHPInclude, 'msf/core/exploit/http/server/php_include'
  17. include Msf::Exploit::Remote::TcpServer
  18. include Msf::Auxiliary::Report
  19. def initialize(info = {})
  20. super
  21. register_options(
  22. [
  23. OptString.new('URIPATH', [ false, "The URI to use for this exploit (default is random)"]),
  24. ], Exploit::Remote::HttpServer
  25. )
  26. register_evasion_options(
  27. [
  28. OptBool.new('HTTP::chunked', [false, 'Enable chunking of HTTP responses via "Transfer-Encoding: chunked"', false]),
  29. OptBool.new('HTTP::header_folding', [false, 'Enable folding of HTTP headers', false]),
  30. OptBool.new('HTTP::junk_headers', [false, 'Enable insertion of random junk HTTP headers', false]),
  31. OptEnum.new('HTTP::compression', [false, 'Enable compression of HTTP responses via content encoding', 'none', ['none','gzip','deflate']]),
  32. OptString.new('HTTP::server_name', [true, 'Configures the Server header of all outgoing replies', 'Apache'])
  33. ], Exploit::Remote::HttpServer
  34. )
  35. register_advanced_options([
  36. OptAddress.new('URIHOST', [false, 'Host to use in URI (useful for tunnels)']),
  37. OptPort.new('URIPORT', [false, 'Port to use in URI (useful for tunnels)'])
  38. ])
  39. # Used to keep track of resources added to the service manager by
  40. # this module. see #add_resource and #cleanup
  41. @my_resources = []
  42. @service_path = nil
  43. end
  44. #
  45. # By default, all HTTP servers are not subject to automatic exploitation
  46. #
  47. def autofilter
  48. false
  49. end
  50. #
  51. # Thread-local client accessor
  52. #
  53. def cli
  54. Thread.current[:cli]
  55. end
  56. #
  57. # Thread-local client accessor
  58. #
  59. def cli=(cli)
  60. Thread.current[:cli] = cli
  61. end
  62. def print_prefix
  63. if cli && (respond_to?(:aggressive) && !aggressive?)
  64. super + "#{cli.peerhost.ljust(16)} #{self.shortname} - "
  65. else
  66. super
  67. end
  68. end
  69. #
  70. # Ensures that gzip can be used. If not, an exception is generated. The
  71. # exception is only raised if the DisableGzip advanced option has not been
  72. # set.
  73. #
  74. def use_zlib
  75. if !Rex::Text.zlib_present? && datastore['HTTP::compression']
  76. raise RuntimeError, "zlib support was not detected, yet the HTTP::compression option was set. Don't do that!"
  77. end
  78. end
  79. #
  80. # This method gives a derived class the opportunity to ensure that all
  81. # dependencies are present before initializing the service.
  82. #
  83. # By default, all HTTP server mixins will try to use zlib.
  84. #
  85. def check_dependencies
  86. use_zlib
  87. end
  88. ##
  89. # :category: Exploit::Remote::TcpServer overrides
  90. #
  91. # This mixin starts the HTTP server listener. This routine takes a few
  92. # different hash parameters:
  93. #
  94. # ServerHost => Override the server host to listen on (default to SRVHOST).
  95. # ServerPort => Override the server port to listen on (default to SRVPORT).
  96. # Uri => The URI to handle and the associated procedure to call.
  97. #
  98. #
  99. # TODO: This must be able to take an SSL parameter and not rely
  100. # completely on the datastore. (See dlink_upnp_exec_noauth)
  101. def start_service(opts = {})
  102. check_dependencies
  103. comm = datastore['ListenerComm']
  104. if (comm.to_s == "local")
  105. comm = ::Rex::Socket::Comm::Local
  106. else
  107. comm = nil
  108. end
  109. # Default the server host and port to what is required by the mixin.
  110. opts = {
  111. 'ServerHost' => datastore['SRVHOST'],
  112. 'ServerPort' => datastore['SRVPORT'],
  113. 'Comm' => comm
  114. }.update(opts)
  115. # Start a new HTTP server service.
  116. self.service = Rex::ServiceManager.start(
  117. Rex::Proto::Http::Server,
  118. opts['ServerPort'].to_i,
  119. opts['ServerHost'],
  120. datastore['SSL'], # XXX: Should be in opts, need to test this
  121. {
  122. 'Msf' => framework,
  123. 'MsfExploit' => self,
  124. },
  125. opts['Comm'],
  126. datastore['SSLCert'],
  127. datastore['SSLCompression'],
  128. datastore['SSLCipher']
  129. )
  130. self.service.server_name = datastore['HTTP::server_name']
  131. # Default the procedure of the URI to on_request_uri if one isn't
  132. # provided.
  133. uopts = {
  134. 'Proc' => Proc.new { |cli, req|
  135. self.cli = cli
  136. ( self.respond_to?(:filter_request_uri) &&
  137. filter_request_uri(cli, req)
  138. ) ? nil : on_request_uri(cli, req)
  139. },
  140. 'Path' => resource_uri
  141. }.update(opts['Uri'] || {})
  142. proto = (datastore["SSL"] ? "https" : "http")
  143. # SSLCompression may or may not actually be available. For example, on
  144. # Ubuntu, it's disabled by default, unless the correct environment
  145. # variable is set. See https://github.com/rapid7/metasploit-framework/pull/2666
  146. if proto == "https" and datastore['SSLCompression']
  147. print_status("Intentionally using insecure SSL compression. Your operating system might not respect this!")
  148. end
  149. print_status("Using URL: #{proto}://#{opts['ServerHost']}:#{opts['ServerPort']}#{uopts['Path']}")
  150. if opts['ServerHost'] == '0.0.0.0'
  151. print_status("Local IP: #{proto}://#{Rex::Socket.source_address('1.2.3.4')}:#{opts['ServerPort']}#{uopts['Path']}")
  152. end
  153. add_resource(uopts)
  154. end
  155. # Set {#on_request_uri} to handle the given +uri+ in addition to the one
  156. # specified by the user in URIPATH.
  157. #
  158. # @note This MUST be called from {#primer} so that the service has been set
  159. # up but we have not yet entered the listen/accept loop.
  160. #
  161. # @param uri [String] The resource URI that should be handled by
  162. # {#on_request_uri}.
  163. # @return [void]
  164. def hardcoded_uripath(uri)
  165. proc = Proc.new do |cli, req|
  166. on_request_uri(cli, req)
  167. end
  168. vprint_status("Adding hardcoded uri #{uri}")
  169. begin
  170. add_resource({'Path' => uri, 'Proc' => proc})
  171. rescue RuntimeError => e
  172. print_error("This module requires a hardcoded uri at #{uri}. Can't run while other modules are using it.")
  173. raise e
  174. end
  175. end
  176. # Take care of removing any resources that we created
  177. def cleanup
  178. # Must dup here because remove_resource modifies @my_resources
  179. @my_resources.dup.each do |resource|
  180. remove_resource(resource)
  181. end
  182. super
  183. end
  184. #
  185. # Return a Hash containing a best guess at the actual browser and operating
  186. # system versions, based on the User-Agent header.
  187. #
  188. # Keys in the returned hash are similar to those expected of
  189. # Report#report_client, and Msf::DBManager#report_host namely:
  190. # +:ua_name+:: a brief identifier for the client, e.g. "Firefox"
  191. # +:ua_ver+:: the version number of the client, e.g. "3.0.11"
  192. # +:os_name+:: something like "Windows XP", "Windows 7", or "Linux"
  193. # +:os_flavor+:: something like "Enterprise", "Pro", or "Home"
  194. # +:os_lang+:: something like "English", "French", or "en-US"
  195. # +:arch+:: one of the ARCH_* constants
  196. #
  197. # Unknown values may be nil.
  198. #
  199. def fingerprint_user_agent(ua_str)
  200. fp = { :ua_string => ua_str }
  201. # Guess the browser type based on the user agent
  202. # Check for IE last since its often impersonated
  203. case (ua_str.downcase)
  204. # Chrome tries to look like Safari, so check it first
  205. when /chrome\/(\d+(:?\.\d+)*)/
  206. # Matches, e.g.:
  207. # Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63 Safari/534.3
  208. fp[:ua_name] = HttpClients::CHROME
  209. fp[:ua_ver] = $1
  210. when /version\/(\d+(:?\.\d+)*)\s*safari/
  211. fp[:ua_name] = HttpClients::SAFARI
  212. fp[:ua_ver] = $1
  213. when /firefox\/((:?[0-9]+\.)+[0-9]+)/
  214. fp[:ua_name] = HttpClients::FF
  215. fp[:ua_ver] = $1
  216. when /opera\/(\d+(:?\.\d+)*)/
  217. fp[:ua_name] = HttpClients::OPERA
  218. fp[:ua_ver] = $1
  219. when /mozilla\/[0-9]+\.[0-9] \(compatible; msie ([0-9]+\.[0-9]+)/i, /mozilla\/[0-9]+\.[0-9] \(.+ rv:([0-9]+\.[0-9])\)/i
  220. fp[:ua_name] = HttpClients::IE
  221. fp[:ua_ver] = $1
  222. else
  223. fp[:ua_name] = HttpClients::UNKNOWN
  224. end
  225. # Guess the language
  226. case (ua_str.downcase)
  227. when /(en-us|en-gb)/
  228. fp[:os_lang] = $1
  229. end
  230. # Guess the general OS type
  231. case (ua_str.downcase)
  232. when /windows|win32/
  233. fp[:os_name] = OperatingSystems::WINDOWS
  234. fp[:arch] = ARCH_X86
  235. when /linux/
  236. fp[:os_name] = OperatingSystems::LINUX
  237. when /iphone|ipad/
  238. fp[:os_name] = OperatingSystems::APPLE_IOS
  239. fp[:arch] = 'armle'
  240. when /mac os x/
  241. fp[:os_name] = OperatingSystems::MAC_OSX
  242. else
  243. fp[:os_name] = OperatingSystems::UNKNOWN
  244. end
  245. # Determine the specific OS variant
  246. # Note that we assume windows variants are the
  247. # client version and mismatch server editions.
  248. case (ua_str.downcase)
  249. when /windows 95/
  250. fp[:os_name] = 'Windows 95'
  251. when /windows 98/
  252. fp[:os_name] = 'Windows 98'
  253. when /windows nt 4/
  254. fp[:os_name] = 'Windows NT'
  255. when /windows nt 5.0/
  256. fp[:os_name] = 'Windows 2000'
  257. when /windows nt 5.1/
  258. fp[:os_name] = 'Windows XP'
  259. when /windows nt 5.2/
  260. fp[:os_name] = 'Windows 2003'
  261. when /windows nt 6.0/
  262. fp[:os_name] = 'Windows Vista'
  263. when /windows nt 6.1/
  264. fp[:os_name] = 'Windows 7'
  265. when /windows nt 6.2/
  266. fp[:os_name] = 'Windows 8'
  267. when /windows nt 6.3/
  268. fp[:os_name] = 'Windows 8.1'
  269. when /gentoo/
  270. fp[:os_vendor] = 'Gentoo'
  271. when /debian/
  272. fp[:os_vendor] = 'Debian'
  273. when /ubuntu/
  274. fp[:os_vendor] = 'Ubuntu'
  275. when /fedora/
  276. fp[:os_vendor] = 'Fedora'
  277. when /red hat|rhel/
  278. fp[:os_vendor] = 'RHEL'
  279. when /android/
  280. fp[:os_name] = OperatingSystems::ANDROID
  281. end
  282. # Guess the architecture
  283. case (ua_str.downcase)
  284. when /ppc/
  285. fp[:arch] = ARCH_PPC
  286. when /x64|x86_64/
  287. fp[:arch] = ARCH_X86_64
  288. when /i.86|wow64/
  289. # WOW64 means "Windows on Windows64" and is present
  290. # in the useragent of 32-bit IE running on 64-bit
  291. # Windows
  292. fp[:arch] = ARCH_X86
  293. when /android|iphone|ipod|ipad/
  294. fp[:arch] = ARCH_ARMLE
  295. else
  296. fp[:arch] = ARCH_X86
  297. end
  298. fp
  299. end
  300. #
  301. # Store the results of server-side User-Agent fingerprinting in the DB.
  302. #
  303. # Returns a Hash containing host and client information.
  304. #
  305. def report_user_agent(address, request, client_opts={})
  306. fp = fingerprint_user_agent(request["User-Agent"])
  307. host = {
  308. :address => address,
  309. :host => address,
  310. }
  311. host[:os_name] = fp[:os_name] if fp[:os_name]
  312. host[:os_flavor] = fp[:os_flavor] if fp[:os_flavor]
  313. host[:arch] = fp[:arch] if fp[:arch]
  314. host[:os_lang] = fp[:os_lang] if fp[:os_lang]
  315. report_host(host)
  316. client = {
  317. :host => address,
  318. :ua_string => request['User-Agent'],
  319. }
  320. client[:ua_name] = fp[:ua_name] if fp[:ua_name]
  321. client[:ua_ver] = fp[:ua_ver] if fp[:ua_ver]
  322. client.merge!(client_opts) if client_opts
  323. report_client(client)
  324. report_note(
  325. :host => address,
  326. :type => 'http.request',
  327. :data => "#{address}: #{request.method} #{request.resource} #{client[:os_name]} #{client[:ua_name]} #{client[:ua_ver]}",
  328. :update => :unique_data
  329. )
  330. return host.merge(client)
  331. end
  332. #
  333. # Adds a URI resource using the supplied hash parameters.
  334. #
  335. # Path => The path to associate the procedure with.
  336. # Proc => The procedure to call when the URI is requested.
  337. # LongCall => Indicates that the request is a long call.
  338. #
  339. # NOTE: Calling #add_resource will change the results of subsequent calls
  340. # to #get_resource!
  341. #
  342. # @return (see Rex::Service#add_resource)
  343. def add_resource(opts)
  344. @service_path = opts['Path']
  345. res = service.add_resource(opts['Path'], opts)
  346. # This has to go *after* the call to service.add_resource in case
  347. # the service manager doesn't like it for some reason and raises.
  348. @my_resources.push(opts['Path'])
  349. res
  350. end
  351. #
  352. # Returns the last-used resource path
  353. #
  354. def get_resource
  355. # We don't want modules modifying their service_path inadvertently, so
  356. # give them a dup. Can be nil during module setup.
  357. @service_path ? @service_path.dup : nil
  358. end
  359. #
  360. # Return a full url of the form <tt>http://1.1.1.1:8080/resource/</tt>
  361. #
  362. # The address portion should be something a client would be able to route,
  363. # but see {#srvhost_addr} for caveats.
  364. #
  365. def get_uri(cli=self.cli)
  366. ssl = !!(datastore["SSL"])
  367. proto = (ssl ? "https://" : "http://")
  368. if datastore['URIHOST']
  369. host = datastore['URIHOST']
  370. elsif (cli and cli.peerhost)
  371. host = Rex::Socket.source_address(cli.peerhost)
  372. else
  373. host = srvhost_addr
  374. end
  375. if Rex::Socket.is_ipv6?(host)
  376. host = "[#{host}]"
  377. end
  378. if datastore['URIPORT'] != 0
  379. port = ':' + datastore['URIPORT'].to_s
  380. elsif (ssl and datastore["SRVPORT"] == 443)
  381. port = ''
  382. elsif (!ssl and datastore["SRVPORT"] == 80)
  383. port = ''
  384. else
  385. port = ":" + datastore["SRVPORT"].to_s
  386. end
  387. uri = proto + host + port + get_resource
  388. uri
  389. end
  390. #
  391. # An address to which the client can route.
  392. #
  393. # If available, return LHOST which should be the right thing since it
  394. # already has to be an address the client can route to for the payload to
  395. # work. However, LHOST will only be available if we're using a reverse_*
  396. # payload, so if we don't have it, try to use the client's peerhost
  397. # address. Failing that, fall back to the addr with the default gateway.
  398. # All of this will be for naught in the case of a user behind NAT using a
  399. # bind payload but there's nothing we can do about it.
  400. #
  401. # NOTE: The address will be *incorrect* in the following two situations:
  402. # 1. LHOST is pointed at a exploit/multi/handler on some other box.
  403. # 2. SRVHOST has a value of '0.0.0.0', the user is behind NAT, and we're
  404. # using a bind payload. In that case, we don't have an LHOST and
  405. # the source address will be internal.
  406. #
  407. # This can potentially be dealt with in a module by using the Host header
  408. # from a request if such a header exists.
  409. #
  410. # @return [String]
  411. def srvhost_addr
  412. if datastore['URIHOST']
  413. host = datastore['URIHOST']
  414. elsif (datastore['LHOST'] and (!datastore['LHOST'].strip.empty?))
  415. host = datastore["LHOST"]
  416. else
  417. if (datastore['SRVHOST'] == "0.0.0.0" or datastore['SRVHOST'] == "::")
  418. if (respond_to?(:sock) and sock and sock.peerhost)
  419. # Then this is a Passive-Aggressive module. It has a socket
  420. # connected to the remote server from which we can deduce the
  421. # appropriate source address.
  422. host = Rex::Socket.source_address(sock.peerhost)
  423. else
  424. # Otherwise, this module is only a server, not a client, *and*
  425. # the payload does not have an LHOST option. This can happen,
  426. # for example, with a browser exploit using a download-exec
  427. # payload. In that case, just use the address of the interface
  428. # with the default gateway and hope for the best.
  429. host = Rex::Socket.source_address
  430. end
  431. else
  432. host = datastore['SRVHOST']
  433. end
  434. end
  435. host
  436. end
  437. #
  438. # Removes a URI resource.
  439. #
  440. def remove_resource(name)
  441. # Guard against removing resources added by other modules
  442. if @my_resources.include?(name)
  443. @my_resources.delete(name)
  444. service.remove_resource(name) if service
  445. end
  446. end
  447. #
  448. # Closes a client connection.
  449. #
  450. def close_client(cli)
  451. service.close_client(cli)
  452. end
  453. #
  454. # Creates an HTTP response packet.
  455. #
  456. def create_response(code = 200, message = "OK", proto = Rex::Proto::Http::DefaultProtocol)
  457. res = Rex::Proto::Http::Response.new(code, message, proto);
  458. res['Content-Type'] = 'text/html'
  459. res
  460. end
  461. #
  462. # Transmits a response to the supplied client, default content-type is text/html
  463. #
  464. # Payload evasions are implemented here!
  465. #
  466. def send_response(cli, body, headers = {})
  467. response = create_response
  468. response['Content-Type'] = 'text/html'
  469. response.body = body.to_s.unpack("C*").pack("C*")
  470. if (datastore['HTTP::compression'])
  471. self.use_zlib # make sure...
  472. response.compress = datastore['HTTP::compression']
  473. end
  474. if datastore['HTTP::chunked']
  475. response.auto_cl = false
  476. response.transfer_chunked = true
  477. end
  478. if datastore['HTTP::header_folding']
  479. response.headers.fold = 1
  480. end
  481. if datastore['HTTP::junk_headers']
  482. response.headers.junk_headers = 1
  483. end
  484. headers.each_pair { |k,v| response[k] = v }
  485. cli.send_response(response)
  486. end
  487. #
  488. # Sends a 302 redirect to the client
  489. #
  490. def send_redirect(cli, location='/', body='', headers = {})
  491. response = create_response(302, 'Moved')
  492. response['Content-Type'] = 'text/html'
  493. response['Location'] = location
  494. response.body = body.to_s.unpack("C*").pack("C*")
  495. headers.each_pair { |k,v| response[k] = v }
  496. cli.send_response(response)
  497. end
  498. #
  499. # Sends a 302 redirect relative to our base path
  500. #
  501. def send_local_redirect(cli, location)
  502. send_redirect(cli, get_resource + location)
  503. end
  504. #
  505. # Sends a 404
  506. #
  507. def send_not_found(cli)
  508. resp_404 = create_response(404, 'Not Found')
  509. resp_404.body = %Q{\
  510. <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
  511. <html><head>
  512. <title>404 Not Found</title>
  513. </head><body>
  514. <h1>Not Found</h1>
  515. <p>The requested URL was not found on this server.</p>
  516. <hr>
  517. <address>Apache/2.2.9 (Unix) Server at #{datastore['LHOST']} Port #{datastore['SRVPORT']}</address>
  518. </body></html>
  519. }
  520. cli.send_response(resp_404)
  521. end
  522. #
  523. # Returns the configured (or random, if not configured) URI path
  524. #
  525. def resource_uri
  526. path = datastore['URIPATH'] || random_uri
  527. path = '/' + path if path !~ /^\//
  528. return path
  529. end
  530. #
  531. # Generates a random URI for use with making finger printing more
  532. # challenging.
  533. #
  534. def random_uri
  535. "/" + Rex::Text.rand_text_alphanumeric(rand(10) + 6)
  536. end
  537. #
  538. # Re-generates the payload, substituting the current RHOST and RPORT with
  539. # the supplied client host and port.
  540. #
  541. def regenerate_payload(cli, arch = nil, platform = nil, target = nil)
  542. pcode = nil
  543. # If the payload fails to generate for some reason, send a 403.
  544. if ((pcode = super(cli, arch, platform, target)) == nil)
  545. print_error("Failed to generate payload, sending 403.")
  546. cli.send_response(
  547. create_response(403, 'Forbidden'))
  548. return nil
  549. end
  550. pcode
  551. end
  552. ##
  553. #
  554. # Override methods
  555. #
  556. ##
  557. #
  558. # Called when a request is made to a single URI registered during the
  559. # start_service. Subsequent registrations will not result in a call to
  560. # on_request_uri.
  561. #
  562. # Modules should override this method.
  563. #
  564. def on_request_uri(cli, request)
  565. end
  566. # allow this module to be patched at initialization-time
  567. Metasploit::Concern.run(self)
  568. end
  569. end