diff options
-rw-r--r-- | changelogs/unreleased/security-ssrf-outbound-request.yml | 5 | ||||
-rw-r--r-- | lib/gitlab/url_blocker.rb | 4 | ||||
-rw-r--r-- | spec/lib/gitlab/url_blocker_spec.rb | 15 |
3 files changed, 23 insertions, 1 deletions
diff --git a/changelogs/unreleased/security-ssrf-outbound-request.yml b/changelogs/unreleased/security-ssrf-outbound-request.yml new file mode 100644 index 00000000000..e67360fdbbf --- /dev/null +++ b/changelogs/unreleased/security-ssrf-outbound-request.yml @@ -0,0 +1,5 @@ +--- +title: Fix DNS rebinding protection bypass when allowing an IP address in Outbound Requests setting +merge_request: +author: +type: security diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb index eece2c343d2..10822f943b6 100644 --- a/lib/gitlab/url_blocker.rb +++ b/lib/gitlab/url_blocker.rb @@ -49,10 +49,12 @@ module Gitlab return [uri, nil] unless address_info ip_address = ip_address(address_info) - return [uri, nil] if domain_allowed?(uri) || ip_allowed?(ip_address, port: get_port(uri)) + return [uri, nil] if domain_allowed?(uri) protected_uri_with_hostname = enforce_uri_hostname(ip_address, uri, dns_rebind_protection) + return protected_uri_with_hostname if ip_allowed?(ip_address, port: get_port(uri)) + # Allow url from the GitLab instance itself but only for the configured hostname and ports return protected_uri_with_hostname if internal?(uri) diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb index f466d117851..686382dc262 100644 --- a/spec/lib/gitlab/url_blocker_spec.rb +++ b/spec/lib/gitlab/url_blocker_spec.rb @@ -91,6 +91,21 @@ RSpec.describe Gitlab::UrlBlocker, :stub_invalid_dns_only do end end + context 'DNS rebinding protection with IP allowed' do + let(:import_url) { 'http://a.192.168.0.120.3times.127.0.0.1.1time.repeat.rebind.network:9121/scrape?target=unix:///var/opt/gitlab/redis/redis.socket&check-keys=*' } + + before do + stub_dns(import_url, ip_address: '192.168.0.120') + + allow(Gitlab::UrlBlockers::UrlAllowlist).to receive(:ip_allowed?).and_return(true) + end + + it_behaves_like 'validates URI and hostname' do + let(:expected_uri) { 'http://192.168.0.120:9121/scrape?target=unix:///var/opt/gitlab/redis/redis.socket&check-keys=*' } + let(:expected_hostname) { 'a.192.168.0.120.3times.127.0.0.1.1time.repeat.rebind.network' } + end + end + context 'disabled DNS rebinding protection' do subject { described_class.validate!(import_url, dns_rebind_protection: false) } |