SECURITY: bypass long GET requests

In some rare cases we would check URLs with very large payloads
this ensures we always bypass and do not read entire payloads
This commit is contained in:
Sam 2019-02-27 14:51:15 +11:00
parent ef9b249cd2
commit cfddfa6de2
1 changed files with 21 additions and 8 deletions

View File

@ -88,12 +88,26 @@ class FinalDestination
end end
def small_get(headers) def small_get(headers)
status_code, headers = nil
catch(:done) do
Net::HTTP.start(@uri.host, @uri.port, use_ssl: @uri.is_a?(URI::HTTPS)) do |http| Net::HTTP.start(@uri.host, @uri.port, use_ssl: @uri.is_a?(URI::HTTPS)) do |http|
http.open_timeout = timeout http.open_timeout = timeout
http.read_timeout = timeout http.read_timeout = timeout
http.request_get(@uri.request_uri, headers) http.request_get(@uri.request_uri, headers) do |resp|
status_code = resp.code.to_i
headers = resp.to_hash
# see: https://bugs.ruby-lang.org/issues/15624
# if we allow response to return then body will be read
# got to abort without reading body
throw :done
end end
end end
end
[status_code, headers]
end
# this is a new interface for simply getting # this is a new interface for simply getting
# N bytes accounting for all internal logic # N bytes accounting for all internal logic
@ -177,20 +191,19 @@ class FinalDestination
@status = :resolved @status = :resolved
return @uri return @uri
when 400, 405, 406, 409, 501 when 400, 405, 406, 409, 501
get_response = small_get(request_headers) response_status, small_headers = small_get(request_headers)
response_status = get_response.code.to_i
if response_status == 200 if response_status == 200
@status = :resolved @status = :resolved
return @uri return @uri
end end
response_headers = {} response_headers = {}
if cookie_val = get_response.get_fields('set-cookie') if cookie_val = small_headers['set-cookie']
response_headers[:cookies] = cookie_val response_headers[:cookies] = cookie_val
end end
if location_val = get_response.get_fields('location') if location_val = small_headers['location']
response_headers[:location] = location_val.join response_headers[:location] = location_val.join
end end
end end