Use validated URL when sending request to Gitea Importer

This change removes possibility to perform DNS Rebinding attack in Gitea
Importer.

Changelog: security
parent 8fd43458
......@@ -66,11 +66,13 @@ class Import::GiteaController < Import::GithubController
override :client_options
def client_options
{ host: provider_url, api_version: 'v1' }
verified_url, provider_hostname = verify_blocked_uri
{ host: verified_url.scheme == 'https' ? provider_url : verified_url.to_s, api_version: 'v1', hostname: provider_hostname }
end
def verify_blocked_uri
Gitlab::UrlBlocker.validate!(
@verified_url_and_hostname ||= Gitlab::UrlBlocker.validate!(
provider_url,
allow_localhost: allow_local_requests?,
allow_local_network: allow_local_requests?,
......
......@@ -8,9 +8,10 @@ module Gitlab
attr_reader :access_token, :host, :api_version, :wait_for_rate_limit_reset
def initialize(access_token, host: nil, api_version: 'v3', wait_for_rate_limit_reset: true)
def initialize(access_token, host: nil, api_version: 'v3', wait_for_rate_limit_reset: true, hostname: nil)
@access_token = access_token
@host = host.to_s.sub(%r{/+\z}, '')
@hostname = hostname
@api_version = api_version
@users = {}
@wait_for_rate_limit_reset = wait_for_rate_limit_reset
......@@ -28,7 +29,8 @@ module Gitlab
# If there is no config, we're connecting to github.com and we
# should verify ssl.
connection_options: {
ssl: { verify: config ? config['verify_ssl'] : true }
ssl: { verify: config ? config['verify_ssl'] : true },
headers: { host: @hostname }.compact
}
)
end
......
......@@ -54,6 +54,48 @@ RSpec.describe Import::GiteaController do
end
end
end
context 'when DNS Rebinding protection is enabled' do
let(:token) { 'gitea token' }
let(:ip_uri) { 'http://167.99.148.217' }
let(:uri) { 'try.gitea.io' }
let(:https_uri) { "https://#{uri}" }
let(:http_uri) { "http://#{uri}" }
before do
session[:gitea_access_token] = token
allow(Gitlab::UrlBlocker).to receive(:validate!).with(https_uri, anything).and_return([Addressable::URI.parse(https_uri), uri])
allow(Gitlab::UrlBlocker).to receive(:validate!).with(http_uri, anything).and_return([Addressable::URI.parse(ip_uri), uri])
allow(Gitlab::LegacyGithubImport::Client).to receive(:new).and_return(double('Gitlab::LegacyGithubImport::Client', repos: [], orgs: []))
end
context 'when provided host url is using https' do
let(:host_url) { https_uri }
it 'uses unchanged host url to send request to Gitea' do
expect(Gitlab::LegacyGithubImport::Client).to receive(:new).with(token, host: https_uri, api_version: 'v1', hostname: 'try.gitea.io')
get :status, format: :json
expect(response).to have_gitlab_http_status(:ok)
end
end
context 'when provided host url is using http' do
let(:host_url) { http_uri }
it 'uses changed host url to send request to Gitea' do
expect(Gitlab::LegacyGithubImport::Client).to receive(:new).with(token, host: 'http://167.99.148.217', api_version: 'v1', hostname: 'try.gitea.io')
get :status, format: :json
expect(response).to have_gitlab_http_status(:ok)
end
end
end
end
end
......
......@@ -86,6 +86,15 @@ RSpec.describe Gitlab::LegacyGithubImport::Client do
it 'builds a endpoint with the given options' do
expect(client.api.api_endpoint).to eq 'https://try.gitea.io/api/v3/'
end
context 'and hostname' do
subject(:client) { described_class.new(token, host: 'https://167.99.148.217/', api_version: 'v1', hostname: 'try.gitea.io') }
it 'builds a endpoint with the given options' do
expect(client.api.connection_options.dig(:headers, :host)).to eq 'try.gitea.io'
expect(client.api.api_endpoint).to eq 'https://167.99.148.217/api/v1/'
end
end
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment