# # ronin-exploits - A Ruby library for ronin-rb that provides exploitation and # payload crafting functionality. # # Copyright (c) 2007-2022 Hal Brodigan (postmodern.mod3 at gmail.com) # # ronin-exploits is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # ronin-exploits is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with ronin-exploits. If not, see . # require 'ronin/support/network/http' require 'ronin/exploits/params/base_url' module Ronin module Exploits module Mixins # # Adds HTTP helper methods for communicating with a web server. # # @api public # # @since 1.0.0 # module HTTP # # Adds the required `base_url` params to the exploit class. # # @param [Class] exploit # The exploit class that included {Mixins::HTTP}. # # @api private # def self.included(exploit) exploit.include Params::BaseURL exploit.param :http_proxy, desc: 'The HTTP proxy to use' exploit.param :http_user, desc: 'The HTTP Basic-Auth user' exploit.param :http_password, desc: 'The HTTP Basic-Auth password' user_agent_ids = [ :random, :chrome, :firefox, :safari, :linux, :macos, :windows, :iphone, :ipad, :android ] + Support::Network::HTTP::UserAgents::ALIASES.keys exploit.param :user_agent, Core::Params::Types::Enum.new(user_agent_ids), desc: 'The HTTP User-Agent to select' exploit.param :raw_user_agent, desc: 'The raw HTTP User-Agent string to use' exploit.param :http_cookie, desc: 'The raw HTTP Cookie to use' end # # The HTTP proxy to use for all HTTP requests. # # @return [String, nil] # # @api private # def http_proxy params[:http_proxy] end # # The HTTP `Basic-Auth` user to use for all HTTP requests. # # @return [String, nil] # # @api private # def http_user params[:http_user] end # # The HTTP `Basic-Auth` password to use for all HTTP requests. # # @return [String, nil] # # @api private # def http_password params[:http_password] end # # Additional default headers to send with every HTTP request. # # @return [Hash{Symbol,String => String,Array}] # # @api private # def http_headers {} end # # The `User-Agent` to use for HTTP requests. # # @return [String, Symbol, :random, nil] # The `User-Agent` string or an alias name (ex: `:chrome_linux`). # # @api private # def http_user_agent params[:raw_user_agent] || params[:user_agent] end # # The `Cookie` to use for HTTP requests. # # @return [String, nil] # # @api private # def http_cookie params[:http_cookie] end # # @!macro request_kwargs # @option kwargs [String, nil] :user (http_user) # The `Basic-Auth` user to authenticate as. # # @option kwargs [String, nil] :password (http_password) # The `Basic-Auth` password to authenticate with. # # @option kwargs [String, nil] :query # The query-string to append to the request path. # # @option kwargs [Hash, nil] :query_params # The query-params to append to the request path. # # @option kwargs [String, nil] :body # The body of the request. # # @option kwargs [Hash, String, nil] :form_data # The form data that may be sent in the body of the request. # # @option kwargs [String, nil] :user (http_user) # The user to authenticate as. # # @option kwargs [String, nil] :password (http_password) # The password to authenticate with. # # @option kwargs [Hash{Symbol,String => String}, nil] :headers # Additional HTTP headers to use for the request. # # # A persistent HTTP connection to the target host and port. # # @return [Ronin::Support::Network::HTTP] # The HTTP connection. # # @note # This method will lazily initialize the HTTP connection on the first # time this method is called and memoize the HTTP object. # def http @http ||= Support::Network::HTTP.connect_uri( params[:base_url], proxy: http_proxy, headers: http_headers, user_agent: http_user_agent, cookie: http_cookie, user: http_user, password: http_password ) end # # Performs and arbitrary HTTP request. # # @param [Symbol, String] method # The HTTP method to use for the request. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # # @raise [ArgumentError] # The `:method` option did not match a known `Net::HTTP` request # class. # def http_request(method,path,**kwargs,&block) if debug? print_debug "Sending #{method.upcase} request to #{url_for(path)} ..." end http.request(method,path,**kwargs,&block) end # # Sends an arbitrary HTTP request and returns the response status. # # @param [Symbol, String] method # The HTTP method to use for the request. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @return [Integer] # The status code of the response. # def http_response_status(method=:head,path,**kwargs) if debug? print_debug "Checking response status for #{method.upcase} #{url_for(path)} ..." end http.response_status(method,path,**kwargs) end # # Sends a HTTP request and determines if the response status was 200. # # @param [Symbol, String] method # The HTTP method to use for the request. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @return [Boolean] # Indicates that the response status was 200. # def http_ok?(method=:head,path,**kwargs) if debug? print_debug "Checking if response status for #{method.upcase} #{url_for(path)} is 200 ..." end http.ok?(method,path,**kwargs) end # # Sends an arbitrary HTTP request and returns the response headers. # # @param [Symbol, String] method # The HTTP method to use for the request. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @return [Hash{String => String}] # The response headers. # def http_response_headers(method=:head,path,**kwargs) if debug? print_debug "Requesting response headers for #{method.upcase} #{url_for(path)} ..." end http.response_headers(method,path,**kwargs) end # # Sends an HTTP request and returns the `Server` header. # # @param [String] path # The path to create the HTTP request for. # # @param [:copy, :delete, :get, :head, :lock, :mkcol, :move, # :options, :patch, :post, :propfind, :proppatch, :put, # :trace, :unlock] method # The HTTP method to use for the request. # # @!macro request_kwargs # # @return [String, nil] # The `Server` header. # def http_server_header(path, method: :head, **kwargs) if debug? print_debug "Requesting the 'Server' header for #{method.upcase} #{url_for(path)} ..." end http.server_header(path, method: method, **kwargs) end # # Sends an HTTP request and returns the `X-Powered-By` header. # # @param [String] path # The path to create the HTTP request for. # # @param [:copy, :delete, :get, :head, :lock, :mkcol, :move, # :options, :patch, :post, :propfind, :proppatch, :put, # :trace, :unlock] method # The HTTP method to use for the request. # # @!macro request_kwargs # # @return [String, nil] # The `X-Powered-By` header. # def http_powered_by_header(path, method: :head, **kwargs) if debug? print_debug "Requesting the 'X-Powered-By' header for #{method.upcase} #{url_for(path)} ..." end http.powered_by_header(path, method: method, **kwargs) end # # Sends an arbitrary HTTP request and returns the response body. # # @param [Symbol, String] method # The HTTP method to use for the request. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @return [String] # The response body. # def http_response_body(method=:get, path,**kwargs) if debug? print_debug "Requesting response body for #{method.upcase} #{url_for(path)} ..." end http.response_body(method, path,**kwargs) end # # Performs a `COPY` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_copy(path,**kwargs) if debug? print_debug "Requesting COPY #{url_for(path)} ..." end http.copy(path,**kwargs) end # # Performs a `DELETE` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_delete(path,**kwargs,&block) if debug? print_debug "Requesting DELETE #{url_for(path)} ..." end http.delete(path,**kwargs) end # # Performs a `GET` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_get(path,**kwargs,&block) if debug? print_debug "Requesting GET #{url_for(path)} ..." end http.get(path,**kwargs) end # # Performs a `GET` request for the given URI and returns the response # headers. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @return [Hash{String => String}] # The response headers. # def http_get_headers(path,**kwargs) if debug? print_debug "Requesting headers for GET #{url_for(path)} ..." end http.get_headers(path,**kwargs) end # # Sends an HTTP request and returns the parsed `Set-Cookie` # header(s). # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @return [Array, nil] # The parsed `SetCookie` header(s). # def http_get_cookies(path,**kwargs) if debug? print_debug "Getting cookies for #{url_for(path)} ..." end http.get_cookies(path,**kwargs) end # # Performs a `GET` request for the given URI and returns the response # body. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @return [String] # The response body. # def http_get_body(path,**kwargs) if debug? print_debug "Requesting body for GET #{url_for(path)} ..." end http.get_body(path,**kwargs) end # # Performs a `HEAD` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_head(path,**kwargs,&block) if debug? print_debug "Requesting HEAD #{url_for(path)} ..." end http.head(path,**kwargs,&block) end # # Performs a `LOCK` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_lock(path,**kwargs,&block) if debug? print_debug "Requesting LOCK #{url_for(path)} ..." end http.lock(path,**kwargs,&block) end # # Performs a `MKCOL` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_mkcol(path,**kwargs,&block) if debug? print_debug "Requesting MKCOL #{url_for(path)} ..." end http.mkcol(path,**kwargs,&block) end # # Performs a `MOVE` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_move(path,**kwargs,&block) if debug? print_debug "Requesting MOVE #{url_for(path)} ..." end http.move(path,**kwargs,&block) end # # Performs a `OPTIONS` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_options(path,**kwargs,&block) if debug? print_debug "Requesting OPTIONS #{url_for(path)} ..." end http.options(path,**kwargs,&block) end # # Performs a `OPTIONS` HTTP request for the given URI and parses the # `Allow` response header. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Array] # The allowed HTTP request methods for the given URL. # def http_allowed_methods(path,**kwargs,&block) if debug? print_debug "Checking allowed HTTP methods for #{url_for(path)} ..." end http.allowed_methods(path,**kwargs) end # # Performs a `PATCH` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # # @see Network::HTTP.patch # def http_patch(path,**kwargs,&block) if debug? print_debug "Requesting PATCH #{url_for(path)} ..." end http.patch(path,**kwargs,&block) end # # Performs a `POST` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_post(path,**kwargs,&block) if debug? print_debug "Requesting POST #{url_for(path)} ..." end http.post(path,**kwargs,&block) end # # Performs a `POST` request on the given URI and returns the response # headers. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @return [Hash{String => String}] # The response headers. # def http_post_headers(path,**kwargs) if debug? print_debug "Requesting response headers for POST #{url_for(path)} ..." end http.post_headers(path,**kwargs) end # # Performs a `POST` request for the given URI and returns the # response body. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @return [String] # The response body. # def http_post_body(path,**kwargs) if debug? print_debug "Requesting response body for POST #{url_for(path)} ..." end http.post_body(path,**kwargs) end # # Performs a `PROPFIND` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_propfind(path,**kwargs,&block) if debug? print_debug "Requesting PROPFIND #{url_for(path)} ..." end http.propfind(path,**kwargs,&block) end alias http_prop_find http_propfind # # Performs a `PROPPATCH` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_proppatch(path,**kwargs,&block) if debug? print_debug "Requesting PROPPATCH #{url_for(path)} ..." end http.proppatch(path,**kwargs,&block) end alias http_prop_patch http_proppatch # # Performs a `PUT` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_put(path,**kwargs,&block) if debug? print_debug "Requesting PUT #{url_for(path)} ..." end http.put(path,**kwargs,&block) end # # Performs a `TRACE` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_trace(path,**kwargs,&block) if debug? print_debug "Requesting TRACE #{url_for(path)} ..." end http.trace(path,**kwargs,&block) end # # Performs a `UNLOCK` request for the given URI. # # @param [String] path # The path to create the HTTP request for. # # @!macro request_kwargs # # @yield [response] # If a block is given it will be passed the received HTTP response. # # @yieldparam [Net::HTTPRresponse] response # The received HTTP response object. # # @return [Net::HTTPResponse] # The new HTTP Request object. # def http_unlock(path,**kwargs,&block) if debug? print_debug "Requesting UNLOCK #{url_for(path)} ..." end http.unlock(path,**kwargs,&block) end end end end end