Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/anemone/rex_http.rb
Views: 11766
require 'rex'1require 'anemone/page'2require 'anemone/cookie_store'345#6# This is an alternate Anemone::HTTP implementation that uses the Metasploit Rex7# library and the Rex::Proto::Http protocol stack.8#910module Anemone11class HTTP12# Maximum number of redirects to follow on each get_response13# REDIRECT_LIMIT = 51415# CookieStore for this HTTP client16attr_reader :cookie_store1718def initialize(opts = {})19@connections = {}20@opts = opts21@cookie_store = CookieStore.new(@opts[:cookies])22end2324#25# Fetch a single Page from the response of an HTTP request to *url*.26# Just gets the final destination page.27#28def fetch_page(url, referer = nil, depth = nil)29fetch_pages(url, referer, depth).last30end3132#33# Create new Pages from the response of an HTTP request to *url*,34# including redirects35#36def fetch_pages(url, referer = nil, depth = nil)37begin38url = URI(url) unless url.is_a?(URI)39pages = []40get(url, referer) do |response, code, location, redirect_to, response_time|4142page = Page.new(location, :body => response.body.dup,43:code => code,44:headers => response.headers,45:referer => referer,46:depth => depth,47:redirect_to => redirect_to,48:response_time => response_time,49:dirbust => @opts[:dirbust]50)51# Store the associated raw HTTP request52page.request = response.request53pages << page54end5556return pages57rescue => e58if verbose?59puts e.inspect60puts e.backtrace61end62return [Page.new(url, :error => e)]63end64end6566#67# The maximum number of redirects to follow68#69def redirect_limit70@opts[:redirect_limit] || REDIRECT_LIMIT71end7273#74# The user-agent string which will be sent with each request,75# or nil if no such option is set76#77def user_agent78@opts[:user_agent]79end8081#82# The virtual host to override the host header with, per url83# TODO: implement84#85def virtual_host(url)86url.host87end8889#90# Does this HTTP client accept cookies from the server?91#92def accept_cookies?93@opts[:accept_cookies]94end9596private9798#99# Retrieve HTTP responses for *url*, including redirects.100# Yields the response object, response code, and URI location101# for each response.102#103def get(url, referer = nil)104limit = redirect_limit105loc = url106begin107# if redirected to a relative url, merge it with the host of the original108# request url109loc = url.merge(loc) if loc.relative?110111response, response_time = get_response(loc, referer)112code = response.code.to_i113114redirect_to = nil115if code >= 300 and code <= 310116redirect_to = URI(response['location']).normalize117end118119yield response, code, loc, redirect_to, response_time120121122limit -= 1123end while (loc = redirect_to) && allowed?(redirect_to, url) && limit > 0124end125126#127# Get an HTTPResponse for *url*, sending the appropriate User-Agent string128#129# MODIFIED: Change get_response to allow fine tuning of the HTTP request before130# it is sent to the remote system.131#132def get_response(url, referer = nil)133opts = {134'uri' => url.path,135'query' => url.query136}137138opts['agent'] = user_agent if user_agent139opts['cookie'] = @cookie_store.to_s unless @cookie_store.empty? || (!accept_cookies? && @opts[:cookies].nil?)140141head = {}142if referer143head['Referer'] = referer.to_s144end145146if @opts[:http_basic_auth]147head['Authorization'] = "Basic " + @opts[:http_basic_auth]148end149150@opts[:inject_headers].each do |hdr|151k,v = hdr.split(':', 2)152head[k] = v153end154155opts['headers'] = head156157retries = 0158begin159start = Time.now()160161response = nil162request = nil163begin164conn = connection(url)165request = conn.request_raw(opts)166response = conn.send_recv(request, @opts[:timeout] || 10 )167rescue ::Errno::EPIPE, ::Timeout::Error168end169170finish = Time.now()171172response_time = ((finish - start) * 1000).round173@cookie_store.merge!(response['Set-Cookie']) if accept_cookies?174return response, response_time175rescue EOFError176retries += 1177retry unless retries > (@opts[:retry_limit] || 3)178end179end180181def connection(url)182context = { }183context['Msf'] = @opts[:framework] if @opts[:framework]184context['MsfExploit'] = @opts[:module] if @opts[:module]185186conn = Rex::Proto::Http::Client.new(187url.host,188url.port.to_i,189context,190url.scheme == "https",191@opts[:ssl_version],192@opts[:proxies],193@opts[:username],194@opts[:password]195)196197conn.set_config(198'vhost' => virtual_host(url),199'agent' => user_agent,200'domain' => @opts[:domain]201)202203conn204end205206def verbose?207@opts[:verbose]208end209210#211# Allowed to connect to the requested url?212#213def allowed?(to_url, from_url)214to_url.host.nil? || (to_url.host == from_url.host)215end216217end218end219220221