Class: Msf::Plugin::Requests::ConsoleCommandDispatcher
- Inherits:
-
Object
- Object
- Msf::Plugin::Requests::ConsoleCommandDispatcher
- Includes:
- Ui::Console::CommandDispatcher
- Defined in:
- plugins/request.rb
Constant Summary collapse
- HELP_REGEX =
/^-?-h(?:elp)?$/.freeze
Instance Attribute Summary
Attributes included from Ui::Console::CommandDispatcher
Attributes included from Rex::Ui::Text::DispatcherShell::CommandDispatcher
Instance Method Summary collapse
-
#cmd_request(*args) ⇒ nil
The main handler for the request command.
- #commands ⇒ Object
-
#handle_request_http(opts, _opt_parser) ⇒ nil
Perform an HTTP request based on the user specified options.
-
#handle_request_https(opts, opt_parser) ⇒ nil
Perform an HTTPS request based on the user specified options.
-
#help(opt_parser = nil, msg = 'Usage: request [options] uri') ⇒ Object
Print the appropriate help text depending on an optional option parser.
- #name ⇒ Object
-
#output_line(opts, line) ⇒ nil
Output lines based on the provided options.
-
#parse_args(args, type = 'http') ⇒ Array<Hash, Rex::Parser::Arguments>
Parse the provided arguments by dispatching to the correct method based on the specified type.
-
#parse_args_http(args = [], _type = 'http') ⇒ Array<Hash>, Rex::Parser::Arguments
Parse the provided arguments for making HTTP requests.
-
#parse_args_https(args = [], type = 'https') ⇒ Array<Hash, Rex::Parser::Arguments>
Parse the provided arguments for making HTTPS requests.
-
#types ⇒ Array<String>
Dynamically determine the types of requests that are supported based on methods prefixed with “parse_args”.
Methods included from Ui::Console::CommandDispatcher
#active_module, #active_module=, #active_session, #active_session=, #build_range_array, #docs_dir, #framework, #initialize, #load_config, #log_error, #remove_lines
Methods included from Rex::Ui::Text::DispatcherShell::CommandDispatcher
#cmd_help, #cmd_help_help, #cmd_help_tabs, #deprecated_cmd, #deprecated_commands, #deprecated_help, #docs_dir, #help_to_s, included, #initialize, #print, #print_error, #print_good, #print_line, #print_status, #print_warning, #tab_complete_directory, #tab_complete_filenames, #tab_complete_generic, #tab_complete_source_address, #unknown_command, #update_prompt
Instance Method Details
#cmd_request(*args) ⇒ nil
The main handler for the request command.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'plugins/request.rb', line 34 def cmd_request(*args) # short circuit the whole deal if they need help return help if args.empty? return help if args.length == 1 && args.first =~ HELP_REGEX # detect the request type from the uri which must be the last arg given uri = args.last if uri && uri =~ %r{^[A-Za-z]{3,5}://} type = uri.split('://', 2).first else print_error('The last argument must be a valid and supported URI') return help end # parse options opts, opt_parser = parse_args(args, type) if opts && opt_parser # handle any "global" options if opts[:output_file] begin opts[:output_file] = File.new(opts[:output_file], 'w') rescue ::Errno::EACCES, Errno::EISDIR, Errno::ENOTDIR return help(opt_parser, 'Failed to open the specified file for output') end end # hand off the actual request to the appropriate request handler handler_method = "handle_request_#{type}".to_sym if respond_to?(handler_method) # call the appropriate request handler send(handler_method, opts, opt_parser) else # this should be dead code if parse_args is doing it's job correctly help(opt_parser, "No request handler found for type (#{type}).") end elsif types.include? type help(opt_parser) else help end end |
#commands ⇒ Object
15 16 17 18 19 |
# File 'plugins/request.rb', line 15 def commands { 'request' => "Make a request of the specified type (#{types.join(', ')})" } end |
#handle_request_http(opts, _opt_parser) ⇒ nil
Perform an HTTP request based on the user specified options.
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 |
# File 'plugins/request.rb', line 255 def handle_request_http(opts, _opt_parser) uri = opts[:uri] http_client = Rex::Proto::Http::Client.new( uri.host, uri.port, { 'Msf' => framework }, uri.scheme == 'https', opts[:ssl_version] ) if opts[:auth_username] auth_str = opts[:auth_username] + ':' + opts[:auth_password] auth_str = 'Basic ' + Rex::Text.encode_base64(auth_str) opts[:headers]['Authorization'] = auth_str end uri.path = '/' if uri.path.empty? begin http_client.connect req = http_client.request_cgi( 'agent' => opts[:user_agent], 'data' => opts[:data], 'headers' => opts[:headers], 'method' => opts[:method], 'password' => opts[:auth_password], 'query' => uri.query, 'uri' => uri.path, 'username' => opts[:auth_username], 'version' => opts[:version] ) response = http_client.send_recv(req) rescue ::OpenSSL::SSL::SSLError print_error('Encountered an SSL error') rescue ::Errno::ECONNRESET print_error('The connection was reset by the peer') rescue ::EOFError, Errno::ETIMEDOUT, Rex::ConnectionError, ::Timeout::Error print_error('Encountered an error') ensure http_client.close end unless response opts[:output_file].close if opts[:output_file] return nil end if opts[:print_headers] output_line(opts, response.cmd_string) output_line(opts, response.headers.to_s) end output_line(opts, response.body) if opts[:print_body] if opts[:output_file] print_status("Wrote #{opts[:output_file].tell} bytes to #{opts[:output_file].path}") opts[:output_file].close end end |
#handle_request_https(opts, opt_parser) ⇒ nil
Perform an HTTPS request based on the user specified options.
224 225 226 227 |
# File 'plugins/request.rb', line 224 def handle_request_https(opts, opt_parser) # let http do it handle_request_http(opts, opt_parser) end |
#help(opt_parser = nil, msg = 'Usage: request [options] uri') ⇒ Object
Print the appropriate help text depending on an optional option parser.
@return [nil]
344 345 346 347 348 349 350 351 352 |
# File 'plugins/request.rb', line 344 def help(opt_parser = nil, msg = 'Usage: request [options] uri') print_line(msg) if opt_parser print_line(opt_parser.usage) else print_line("Supported uri types are: #{types.collect { |t| t + '://' }.join(', ')}") print_line('To see usage for a specific uri type, use request -h uri') end end |
#name ⇒ Object
11 12 13 |
# File 'plugins/request.rb', line 11 def name 'Request' end |
#output_line(opts, line) ⇒ nil
Output lines based on the provided options. Data is either printed to the console or written to a file. Trailing new lines are removed.
323 324 325 326 327 328 329 330 331 332 333 334 335 |
# File 'plugins/request.rb', line 323 def output_line(opts, line) if opts[:output_file].nil? if line[-2..] == "\r\n" print_line(line[0..-3]) elsif line[-1] == "\n" print_line(line[0..-2]) else print_line(line) end else opts[:output_file].write(line) end end |
#parse_args(args, type = 'http') ⇒ Array<Hash, Rex::Parser::Arguments>
Parse the provided arguments by dispatching to the correct method based on the specified type.
83 84 85 86 87 88 89 90 91 |
# File 'plugins/request.rb', line 83 def parse_args(args, type = 'http') type.downcase! parse_method = "parse_args_#{type}".to_sym if respond_to?(parse_method) send(parse_method, args, type) else print_error("Unsupported URI type: #{type}") end end |
#parse_args_http(args = [], _type = 'http') ⇒ Array<Hash>, Rex::Parser::Arguments
Parse the provided arguments for making HTTP requests. The argument flags are intended to be similar to the curl utility.
112 113 114 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 144 145 146 147 148 149 150 151 152 153 154 155 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 |
# File 'plugins/request.rb', line 112 def parse_args_http(args = [], _type = 'http') opt_parser = Rex::Parser::Arguments.new( '-0' => [ false, 'Use HTTP 1.0' ], '-1' => [ false, 'Use TLSv1 (SSL)' ], '-2' => [ false, 'Use SSLv2 (SSL)' ], '-3' => [ false, 'Use SSLv3 (SSL)' ], '-A' => [ true, 'User-Agent to send to server' ], '-d' => [ true, 'HTTP POST data' ], '-G' => [ false, 'Send the -d data with an HTTP GET' ], '-h' => [ false, 'This help text' ], '-H' => [ true, 'Custom header to pass to server' ], '-i' => [ false, 'Include headers in the output' ], '-I' => [ false, 'Show document info only' ], '-o' => [ true, 'Write output to <file> instead of stdout' ], '-u' => [ true, 'Server user and password' ], '-X' => [ true, 'Request method to use' ] # '-x' => [ true, 'Proxy to use, format: [proto://][user:pass@]host[:port]' + # ' Proto defaults to http:// and port to 1080'], ) = { headers: {}, print_body: true, print_headers: false, ssl_version: 'Auto', user_agent: Rex::UserAgent.session_agent, version: '1.1' } opt_parser.parse(args) do |opt, _idx, val| case opt when '-0' [:version] = '1.0' when '-1' [:ssl_version] = 'TLS1' when '-2' [:ssl_version] = 'SSL2' when '-3' [:ssl_version] = 'SSL3' when '-A' [:user_agent] = val when '-d' [:data] = val [:method] ||= 'POST' when '-G' [:method] = 'GET' when HELP_REGEX # help(opt_parser) # guard to prevent further option processing & stymie request handling return [nil, opt_parser] when '-H' name, value = val.split(':', 2) [:headers][name] = value.to_s.strip when '-i' [:print_headers] = true when '-I' [:print_headers] = true [:print_body] = false [:method] ||= 'HEAD' when '-o' [:output_file] = File.(val) when '-u' val = val.split(':', 2) # only split on first ':' as per curl: # from curl man page: "The user name and passwords are split up on the # first colon, which makes it impossible to use a colon in the user # name with this option. The password can, still. [:auth_username] = val.first [:auth_password] = val.last when '-p' [:auth_password] = val when '-X' [:method] = val # when '-x' # @TODO proxy else [:uri] = val end end unless [:uri] help(opt_parser) end [:method] ||= 'GET' [:uri] = URI([:uri]) [, opt_parser] end |
#parse_args_https(args = [], type = 'https') ⇒ Array<Hash, Rex::Parser::Arguments>
Parse the provided arguments for making HTTPS requests. The argument flags are intended to be similar to the curl utility.
100 101 102 103 |
# File 'plugins/request.rb', line 100 def parse_args_https(args = [], type = 'https') # just let http do it parse_args_http(args, type) end |
#types ⇒ Array<String>
Dynamically determine the types of requests that are supported based on methods prefixed with “parse_args”.
25 26 27 28 |
# File 'plugins/request.rb', line 25 def types parse_methods = public_methods.select { |m| m.to_s =~ /^parse_args_/ } parse_methods.collect { |m| m.to_s.split('_').slice(2..-1).join('_') } end |