Merge pull request #21144 from Nayeraneru/docs/msf-auxiliary-web-http-yard

Enhance documentation for HTTP module methods
This commit is contained in:
cgranleese-r7
2026-03-27 10:53:43 +00:00
committed by GitHub
+124 -1
View File
@@ -11,11 +11,16 @@ require 'uri'
module Msf
class Auxiliary::Web::HTTP
# Wraps a queued HTTP request and the callbacks that should process its response.
class Request
attr_accessor :url
attr_reader :opts
attr_reader :callbacks
# @param url [String, URI] The target URL to request.
# @param opts [Hash] Request options forwarded to {HTTP#request}.
# @yield [response] Handles the completed response.
# @yieldparam response [Response] The received response.
def initialize( url, opts = {}, &callback )
@url = url.to_s.dup
@opts = opts.dup
@@ -25,17 +30,27 @@ class Auxiliary::Web::HTTP
@callbacks = [callback].compact
end
# @return [Symbol] The HTTP verb used when the request is executed.
def method
opts[:method]
end
# Calls each registered callback with the received response.
#
# @param response [Response] The response to dispatch.
# @return [Array<Proc>] The stored callbacks.
def handle_response( response )
callbacks.each { |c| c.call response }
end
end
# Decorates {Rex::Proto::Http::Response} with convenience helpers used by web auxiliaries.
class Response < Rex::Proto::Http::Response
# Builds a response object from a Rex HTTP response.
#
# @param response [Rex::Proto::Http::Response, nil] The response returned by Rex.
# @return [Response] A wrapped response, or {empty} when no response was received.
def self.from_rex_response( response )
return empty if !response
@@ -46,20 +61,28 @@ class Auxiliary::Web::HTTP
r
end
# @return [Response] An empty placeholder response.
def self.empty
new( 0, '' )
end
# Builds an empty response marked as having timed out.
#
# @return [Response] A timeout sentinel response.
def self.timed_out
r = empty
r.timed_out
r
end
# @return [Boolean] True when the request timed out.
def timed_out?
!!@timed_out
end
# Marks this response as timed out.
#
# @return [TrueClass] Always returns true.
def timed_out
@timed_out = true
end
@@ -73,6 +96,13 @@ class Auxiliary::Web::HTTP
attr_accessor :redirect_limit
attr_accessor :username , :password, :domain
# @param opts [Hash] Configuration for the HTTP helper.
# @option opts [Object] :framework The active framework instance used for threading.
# @option opts [Object] :parent The owning module used for error reporting.
# @option opts [Hash] :headers Additional HTTP headers to send with every request.
# @option opts [String] :cookie_string Cookie header value to set by default.
# @option opts [Hash] :auth Default authentication options.
# @option opts [Integer] :redirect_limit Maximum redirects to follow.
def initialize( opts = {} )
@opts = opts.dup
@@ -100,10 +130,17 @@ class Auxiliary::Web::HTTP
@after_run_blocks = []
end
# Registers a callback to be executed after {#run} drains the request queue.
#
# @yield A block to run after all queued requests finish.
# @return [Array<Proc>] The accumulated after-run callbacks.
def after_run( &block )
@after_run_blocks << block
end
# Creates a Rex HTTP client using the configured target and authentication defaults.
#
# @return [Rex::Proto::Http::Client] A configured HTTP client.
def connect
c = Rex::Proto::Http::Client.new(
opts[:target].host,
@@ -126,6 +163,12 @@ class Auxiliary::Web::HTTP
c
end
# Executes all queued asynchronous requests using the configured thread pool size.
#
# Callback exceptions are reported through the parent module and isolated from
# the rest of the queue processing.
#
# @return [void]
def run
return if @queue.empty?
@@ -152,6 +195,12 @@ class Auxiliary::Web::HTTP
call_after_run_blocks
end
# Sends an HTTP request and optionally follows redirect responses.
#
# @param url [String, URI] The URL to request.
# @param opts [Hash] Request options forwarded to {#_request}.
# @option opts [Boolean] :follow_redirect Whether to follow Location headers.
# @return [Response, nil] The final response, or nil when the redirect limit is exceeded.
def request( url, opts = {} )
rlimit = self.redirect_limit
@@ -163,30 +212,74 @@ class Auxiliary::Web::HTTP
nil
end
# Enqueues a request to be sent later by {#run}.
#
# @param url [String, URI] The URL to request.
# @param opts [Hash] Request options.
# @yield [response] Processes the response after execution.
# @yieldparam response [Response] The completed response.
# @return [Queue] The internal request queue.
def request_async( url, opts = {}, &callback )
queue Request.new( url, opts, &callback )
end
# Enqueues a GET request.
#
# @param url [String, URI] The URL to request.
# @param opts [Hash] Additional request options.
# @yield [response] Processes the response after execution.
# @return [Queue] The internal request queue.
def get_async( url, opts = {}, &callback )
request_async( url, opts.merge( :method => :get ), &callback )
end
# Enqueues a POST request.
#
# @param url [String, URI] The URL to request.
# @param opts [Hash] Additional request options.
# @yield [response] Processes the response after execution.
# @return [Queue] The internal request queue.
def post_async( url, opts = {}, &callback )
request_async( url, opts.merge( :method => :post ), &callback )
end
# Sends a synchronous GET request.
#
# @param url [String, URI] The URL to request.
# @param opts [Hash] Additional request options.
# @return [Response, nil] The received response.
def get( url, opts = {} )
request( url, opts.merge( :method => :get ) )
end
# Sends a synchronous POST request.
#
# @param url [String, URI] The URL to request.
# @param opts [Hash] Additional request options.
# @return [Response, nil] The received response.
def post( url, opts = {} )
request( url, opts.merge( :method => :post ) )
end
# Yields only when the supplied response body does not appear to be a custom 404 page.
#
# @param path [String] The original request path.
# @param body [String] The response body to compare.
# @yield Runs when the body is not identified as a custom 404.
# @return [void]
def if_not_custom_404( path, body, &callback )
custom_404?( path, body ) { |b| callback.call if !b }
end
# Determines whether a response body matches the application's custom 404 behavior.
#
# The helper probes several random paths, refines their dynamic content, and compares
# the result to the supplied response body.
#
# @param path [String] The original request path.
# @param body [String] The response body to classify.
# @yieldparam is_custom_404 [Boolean] True when the body matches the custom 404 fingerprint.
# @return [nil] Returns nil immediately and reports the result via the callback.
def custom_404?( path, body, &callback )
return if !path || !body
@@ -257,25 +350,51 @@ class Auxiliary::Web::HTTP
private
# Runs and clears the callbacks registered through {#after_run}.
#
# @return [void]
def call_after_run_blocks
while block = @after_run_blocks.pop
block.call
end
end
# Executes a block while holding the helper's mutex.
#
# @yield The critical section.
# @return [Object] The block result.
def synchronize( &block )
(@mutex ||= Mutex.new).synchronize( &block )
end
# Compares the supplied body to the cached custom 404 signatures for a path.
#
# @param path [String] The original request path.
# @param body [String] The response body to compare.
# @return [Boolean] True when the body matches the cached custom 404 fingerprint.
def is_404?( path, body )
@@_404[path].each { |_404| return true if Rex::Text.refine( _404['body'], body ) == _404['rdiff'] }
false
end
# Appends a request to the internal work queue.
#
# @param request [Request] The queued request wrapper.
# @return [Queue] The internal queue.
def queue( request )
@queue << request
end
# Issues a single HTTP request without following redirects.
#
# @param url [String, URI] The URL to request.
# @param opts [Hash] Request options.
# @option opts [String] :body Optional request body.
# @option opts [Integer] :timeout Request timeout in seconds.
# @option opts [Hash] :params Query string or POST parameters.
# @option opts [Hash] :headers Per-request headers.
# @option opts [Hash] :rex Direct Rex request overrides.
# @return [Response] The response wrapper.
def _request( url, opts = {} )
body = opts[:body]
timeout = opts[:timeout] || 10
@@ -323,6 +442,10 @@ class Auxiliary::Web::HTTP
Response.empty
end
# Prints an error through the owning module when available.
#
# @param message [String] The message to report.
# @return [void]
def print_error( message )
return if !@parent
@parent.print_error message