Module: SsrfFilter::Patch::HTTPGenericRequest

Defined in:
lib/ssrf_filter/patch/http_generic_request.rb

Class Method Summary collapse

Class Method Details

.apply!Object

Apply the patch from the linked commit onto ::Net::HTTPGenericRequest. Since this is 3rd party code, disable code coverage and rubocop linting for this section. :nocov: rubocop:disable all



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/ssrf_filter/patch/http_generic_request.rb', line 30

def self.apply!
  return if instance_variable_defined?(:@checked_http_generic_request)
  @checked_http_generic_request = true
  return unless should_apply?

  ::Net::HTTPGenericRequest.class_eval do
    def exec(sock, ver, path)
      if @body
        send_request_with_body sock, ver, path, @body
      elsif @body_stream
        send_request_with_body_stream sock, ver, path, @body_stream
      elsif @body_data
        send_request_with_body_data sock, ver, path, @body_data
      else
        write_header sock, ver, path
      end
    end

    def update_uri(addr, port, ssl)
      # reflect the connection and @path to @uri
      return unless @uri

      if ssl
        scheme = 'https'.freeze
        klass = URI::HTTPS
      else
        scheme = 'http'.freeze
        klass = URI::HTTP
      end

      if host = self['host']
        host.sub!(/:.*/s, ''.freeze)
      elsif host = @uri.host
      else
       host = addr
      end
      # convert the class of the URI
      if @uri.is_a?(klass)
        @uri.host = host
        @uri.port = port
      else
        @uri = klass.new(
          scheme, @uri.userinfo,
          host, port, nil,
          @uri.path, nil, @uri.query, nil)
      end
    end
  end
end

.should_apply?Boolean

Ruby had a bug in its Http library where if you set a custom ‘Host` header on a request it would get overwritten. This was tracked in: bugs.ruby-lang.org/issues/10054 and resolved with the commit: github.com/ruby/ruby/commit/70a2eb63999265ff7e8d46d1f5b410c8ee3d30d7#diff-5c08b4ae27d2294a8294a27ff9af4a85 Versions of Ruby that don’t have this fix applied will fail to connect to certain hosts via SsrfFilter. The patch below backports the fix from the linked commit.

Returns:

  • (Boolean)


14
15
16
17
18
19
20
21
22
23
24
# File 'lib/ssrf_filter/patch/http_generic_request.rb', line 14

def self.should_apply?
  # Check if the patch needs to be applied:
  # The Ruby bug was that HTTPGenericRequest#exec overwrote the Host header, so this snippet checks
  # if we can reproduce that behavior. It does not actually open any network connections.

  uri = URI('https://www.example.com')
  request = ::Net::HTTPGenericRequest.new('HEAD', false, false, uri)
  request['host'] = '127.0.0.1'
  request.exec(StringIO.new, '1.1', '/')
  request['host'] == uri.hostname
end