Block loopback addresses in UrlBlocker
Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/51128
This commit is contained in:
parent
ab22dae917
commit
b1d04cf9d5
3 changed files with 33 additions and 1 deletions
5
changelogs/unreleased/sh-block-other-localhost.yml
Normal file
5
changelogs/unreleased/sh-block-other-localhost.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Block loopback addresses in UrlBlocker
|
||||||
|
merge_request:
|
||||||
|
author:
|
||||||
|
type: security
|
|
@ -30,6 +30,7 @@ module Gitlab
|
||||||
end
|
end
|
||||||
|
|
||||||
validate_localhost!(addrs_info) unless allow_localhost
|
validate_localhost!(addrs_info) unless allow_localhost
|
||||||
|
validate_loopback!(addrs_info) unless allow_localhost
|
||||||
validate_local_network!(addrs_info) unless allow_local_network
|
validate_local_network!(addrs_info) unless allow_local_network
|
||||||
validate_link_local!(addrs_info) unless allow_local_network
|
validate_link_local!(addrs_info) unless allow_local_network
|
||||||
|
|
||||||
|
@ -84,6 +85,12 @@ module Gitlab
|
||||||
raise BlockedUrlError, "Requests to localhost are not allowed"
|
raise BlockedUrlError, "Requests to localhost are not allowed"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def validate_loopback!(addrs_info)
|
||||||
|
return unless addrs_info.any? { |addr| addr.ipv4_loopback? || addr.ipv6_loopback? }
|
||||||
|
|
||||||
|
raise BlockedUrlError, "Requests to loopback addresses are not allowed"
|
||||||
|
end
|
||||||
|
|
||||||
def validate_local_network!(addrs_info)
|
def validate_local_network!(addrs_info)
|
||||||
return unless addrs_info.any? { |addr| addr.ipv4_private? || addr.ipv6_sitelocal? }
|
return unless addrs_info.any? { |addr| addr.ipv4_private? || addr.ipv6_sitelocal? }
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,16 @@ describe Gitlab::UrlBlocker do
|
||||||
expect(described_class.blocked_url?('https://gitlab.com/foo/foo.git', protocols: ['http'])).to be true
|
expect(described_class.blocked_url?('https://gitlab.com/foo/foo.git', protocols: ['http'])).to be true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns true for localhost IPs' do
|
||||||
|
expect(described_class.blocked_url?('https://0.0.0.0/foo/foo.git')).to be true
|
||||||
|
expect(described_class.blocked_url?('https://[::1]/foo/foo.git')).to be true
|
||||||
|
expect(described_class.blocked_url?('https://127.0.0.1/foo/foo.git')).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns true for loopback IP' do
|
||||||
|
expect(described_class.blocked_url?('https://127.0.0.2/foo/foo.git')).to be true
|
||||||
|
end
|
||||||
|
|
||||||
it 'returns true for alternative version of 127.0.0.1 (0177.1)' do
|
it 'returns true for alternative version of 127.0.0.1 (0177.1)' do
|
||||||
expect(described_class.blocked_url?('https://0177.1:65535/foo/foo.git')).to be true
|
expect(described_class.blocked_url?('https://0177.1:65535/foo/foo.git')).to be true
|
||||||
end
|
end
|
||||||
|
@ -84,6 +94,16 @@ describe Gitlab::UrlBlocker do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'allows localhost endpoints' do
|
||||||
|
expect(described_class).not_to be_blocked_url('http://0.0.0.0', allow_localhost: true)
|
||||||
|
expect(described_class).not_to be_blocked_url('http://localhost', allow_localhost: true)
|
||||||
|
expect(described_class).not_to be_blocked_url('http://127.0.0.1', allow_localhost: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'allows loopback endpoints' do
|
||||||
|
expect(described_class).not_to be_blocked_url('http://127.0.0.2', allow_localhost: true)
|
||||||
|
end
|
||||||
|
|
||||||
it 'allows IPv4 link-local endpoints' do
|
it 'allows IPv4 link-local endpoints' do
|
||||||
expect(described_class).not_to be_blocked_url('http://169.254.169.254')
|
expect(described_class).not_to be_blocked_url('http://169.254.169.254')
|
||||||
expect(described_class).not_to be_blocked_url('http://169.254.168.100')
|
expect(described_class).not_to be_blocked_url('http://169.254.168.100')
|
||||||
|
@ -122,7 +142,7 @@ describe Gitlab::UrlBlocker do
|
||||||
end
|
end
|
||||||
|
|
||||||
def stub_domain_resolv(domain, ip)
|
def stub_domain_resolv(domain, ip)
|
||||||
allow(Addrinfo).to receive(:getaddrinfo).with(domain, any_args).and_return([double(ip_address: ip, ipv4_private?: true, ipv6_link_local?: false)])
|
allow(Addrinfo).to receive(:getaddrinfo).with(domain, any_args).and_return([double(ip_address: ip, ipv4_private?: true, ipv6_link_local?: false, ipv4_loopback?: false, ipv6_loopback?: false)])
|
||||||
end
|
end
|
||||||
|
|
||||||
def unstub_domain_resolv
|
def unstub_domain_resolv
|
||||||
|
|
Loading…
Reference in a new issue