Skip to content

Responses and Debugging

How to inspect responses and check whether a request was sent as expected.

res = send_request_cgi(...)
fail_with(Failure::Unreachable, "#{peer} - no response") if res.nil?
fail_with(Failure::UnexpectedReply, "HTTP #{res.code}") unless res.code == 200
print_status(res.headers['Server'].to_s)
print_line(res.body[0, 200])
cookies = res.get_cookies
loc = res.redirection if res.redirect?
json = res.get_json_document
html = res.get_html_document
xml = res.get_xml_document
inputs = res.get_hidden_inputs
MethodReturn value
get_json_documentParsed JSON value; an empty Hash on a syntax error
get_html_documentNokogiri HTML document
get_xml_documentNokogiri XML document
get_hidden_inputsArray<Hash> containing each form’s hidden fields
get_cookiesCookie string built from Set-Cookie
redirectionURI from the Location header, or nil if unavailable
title = res.get_html_document.at('title')&.text
token = res.get_html_document.at_xpath("//input[@name='csrf_token']/@value")&.text
session_id = res.get_hidden_inputs.dig(0, 'sessionid')

Checking whether an RCE endpoint succeeded

Section titled “Checking whether an RCE endpoint succeeded”

Judge whether execute_command succeeded according to the response the API actually returns.

Actual responseExample handling
Request times out during command executionTreat res.nil? as success only if asynchronous execution can be confirmed
HTTP 200 with JSON (such as {"result": ...})Check res.code == 200 and get_json_document
HTTP 500 HTML error pageInspect the status code, title, and body
res = send_request_cgi(...)
fail_with(Failure::Unreachable, "#{peer} - no response") if res.nil?
json = res.get_json_document
fail_with(Failure::UnexpectedReply, "HTTP #{res.code}") unless res.code == 200 && json.is_a?(Hash) && json.key?('result')

get_json_document returns an empty Hash on a JSON syntax error, so check for the expected key too. In this example, HTTP 200 and a result key are the success conditions.

send_request_cgi({ ... }, datastore['HttpClientTimeout'] || 30)

For slow uploads or logins, increase the module’s advanced HttpClientTimeout option.

set HttpTrace true
set HttpTraceHeadersOnly false
set VERBOSE true
run

You can inspect the raw request and response. Be aware that credentials may remain in logs or spool output.

These evasion options are usually unnecessary in a normal test environment, but HttpClient provides them:

  • HTTP::uri_encode_mode
  • HTTP::pad_get_params / HTTP::pad_post_params
  • HTTP::shuffle_get_params / HTTP::shuffle_post_params
  • HTTP::header_folding
  • HTTP::method_random_case

Check with show evasion / show advanced.

  • Response handling and fail_with
  • URI helpers
  • Bundled wiki: docs/metasploit-framework.wiki/How-to-Send-an-HTTP-Request-Using-HttpClient.md
  • Bundled wiki: docs/metasploit-framework.wiki/How-to-parse-an-HTTP-response.md