lib/arachni/http/request.rb in arachni-1.1 vs lib/arachni/http/request.rb in arachni-1.2
- old
+ new
@@ -99,13 +99,10 @@
# @return [Integer]
# Maximum HTTP response size to accept, in bytes.
attr_accessor :response_max_size
- # @private
- attr_accessor :root_redirect_id
-
# @param [Hash] options
# Request options.
# @option options [String] :url
# URL.
# @option options [Hash] :parameters ({})
@@ -127,10 +124,11 @@
options[:method] ||= :get
super( options )
@train = false if @train.nil?
+ @fingerprint = true if @fingerprint.nil?
@update_cookies = false if @update_cookies.nil?
@follow_location = false if @follow_location.nil?
@max_redirects = (Options.http.request_redirect_limit || REDIRECT_LIMIT)
@on_complete = []
@@ -264,10 +262,17 @@
def follow_location?
!!@follow_location
end
# @return [Bool]
+ # `true` if the {Response} should be {Platform::Manager.fingerprint fingerprinted}
+ # for platforms, `false` otherwise.
+ def fingerprint?
+ @fingerprint
+ end
+
+ # @return [Bool]
# `true` if the {Response} should be analyzed by the {Trainer}
# for new elements, `false` otherwise.
def train?
@train
end
@@ -341,10 +346,14 @@
capath: Options.http.ssl_ca_directory,
sslversion: Options.http.ssl_version,
accept_encoding: 'gzip, deflate',
nosignal: true,
+
+ # If Content-Length is missing this option will have no effect, so
+ # we'll also stream the body to make sure that we can at least abort
+ # the reading of the response body if it exceeds this limit.
maxfilesize: max_size,
# Don't keep the socket alive if this is a blocking request because
# it's going to be performed by an one-off Hydra.
forbid_reuse: blocking?,
@@ -382,21 +391,29 @@
options[:proxyuserpwd] =
"#{Options.http.proxy_username}:#{Options.http.proxy_password}"
end
end
- curl = parsed_url.query ? url.gsub( "?#{parsed_url.query}", '' ) : url
- r = Typhoeus::Request.new( curl, options )
+ curl = parsed_url.query ? url.gsub( "?#{parsed_url.query}", '' ) : url
+ typhoeus_request = Typhoeus::Request.new( curl, options )
if @on_complete.any?
- r.on_complete do |typhoeus_response|
+ response_body_buffer = ''
+ set_body_reader( typhoeus_request, response_body_buffer )
+
+ typhoeus_request.on_complete do |typhoeus_response|
+ if typhoeus_request.options[:maxfilesize]
+ typhoeus_response.options[:response_body] =
+ response_body_buffer
+ end
+
fill_in_data_from_typhoeus_response typhoeus_response
handle_response Response.from_typhoeus( typhoeus_response )
end
end
- r
+ typhoeus_request
end
def to_h
{
url: url,
@@ -478,36 +495,72 @@
name, value = pair.split( '=', 2 )
h[Form.decode( name.to_s )] = Form.decode( value )
h
end
end
+
+ def encode( string )
+ @easy ||= Ethon::Easy.new( url: 'www.example.com' )
+ @easy.escape string
+ end
end
def prepare_headers
- headers['Cookie'] = effective_cookies.
- map { |k, v| "#{Cookie.encode( k )}=#{Cookie.encode( v )}" }.
- join( ';' )
- headers.delete( 'Cookie' ) if headers['Cookie'].empty?
-
headers['User-Agent'] ||= Options.http.user_agent
headers['Accept'] ||= 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
headers['From'] ||= Options.authorized_by if Options.authorized_by
headers.each { |k, v| headers[k] = Header.encode( v ) if v }
+
+ headers['Cookie'] = effective_cookies.
+ map { |k, v| "#{Cookie.encode( k )}=#{Cookie.encode( v )}" }.
+ join( ';' )
+ headers.delete( 'Cookie' ) if headers['Cookie'].empty?
+
+ headers
end
private
+ def client_run
+ typhoeus_request = to_typhoeus
+
+ response_body_buffer = ''
+ set_body_reader( typhoeus_request, response_body_buffer )
+
+ typhoeus_response = typhoeus_request.run
+
+ if typhoeus_request.options[:maxfilesize]
+ typhoeus_response.options[:response_body] = response_body_buffer
+ end
+
+ fill_in_data_from_typhoeus_response typhoeus_response
+
+ Response.from_typhoeus( typhoeus_response )
+ end
+
def fill_in_data_from_typhoeus_response( response )
- @headers_string = response.debug_info.header_out.first
- @effective_body = response.debug_info.data_out.first
+ # Only grab the last data.
+ # In case of CONNECT calls for HTTPS via proxy the first data will be
+ # the proxy-related stuff.
+ @headers_string = response.debug_info.header_out.last
+ @effective_body = response.debug_info.data_out.last
end
- def client_run
- response = to_typhoeus.run
- fill_in_data_from_typhoeus_response response
+ def set_body_reader( typhoeus_request, buffer )
+ return if !typhoeus_request.options[:maxfilesize]
- Response.from_typhoeus( response )
+ aborted = nil
+ typhoeus_request.on_body do |chunk|
+ next aborted if aborted
+
+ if buffer.size >= typhoeus_request.options[:maxfilesize]
+ buffer.clear
+ next aborted = :abort
+ end
+
+ buffer << chunk
+ end
end
end
end
end