diff options
author | Douwe Maan <douwe@selenight.nl> | 2019-04-21 13:03:26 +0300 |
---|---|---|
committer | Oswaldo Ferreira <oswaldo@gitlab.com> | 2019-05-30 16:47:31 +0300 |
commit | a9bcddee4c2653cbf2254d893299393e3778e7df (patch) | |
tree | 0c81c5358bce244da7cf9f9f684234a7f4a2dfd0 /lib/gitlab/http_connection_adapter.rb | |
parent | 88241108c4d9807e5c312b11c910b3072bc6f120 (diff) |
Protect Gitlab::HTTP against DNS rebinding attack
Gitlab::HTTP now resolves the hostname only once, verifies the IP is not
blocked, and then uses the same IP to perform the actual request, while
passing the original hostname in the `Host` header and SSL SNI field.
Diffstat (limited to 'lib/gitlab/http_connection_adapter.rb')
-rw-r--r-- | lib/gitlab/http_connection_adapter.rb | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/lib/gitlab/http_connection_adapter.rb b/lib/gitlab/http_connection_adapter.rb new file mode 100644 index 00000000000..9ccf0653903 --- /dev/null +++ b/lib/gitlab/http_connection_adapter.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +# This class is part of the Gitlab::HTTP wrapper. Depending on the value +# of the global setting allow_local_requests_from_hooks_and_services this adapter +# will allow/block connection to internal IPs and/or urls. +# +# This functionality can be overridden by providing the setting the option +# allow_local_requests = true in the request. For example: +# Gitlab::HTTP.get('http://www.gitlab.com', allow_local_requests: true) +# +# This option will take precedence over the global setting. +module Gitlab + class HTTPConnectionAdapter < HTTParty::ConnectionAdapter + def connection + begin + @uri, hostname = Gitlab::UrlBlocker.validate!(uri, allow_local_network: allow_local_requests?, + allow_localhost: allow_local_requests?) + rescue Gitlab::UrlBlocker::BlockedUrlError => e + raise Gitlab::HTTP::BlockedUrlError, "URL '#{uri}' is blocked: #{e.message}" + end + + super.tap do |http| + http.hostname_override = hostname if hostname + end + end + + private + + def allow_local_requests? + options.fetch(:allow_local_requests, allow_settings_local_requests?) + end + + def allow_settings_local_requests? + Gitlab::CurrentSettings.allow_local_requests_from_hooks_and_services? + end + end +end |