diff options
author | Lin Jen-Shin <godfat@godfat.org> | 2017-11-10 15:33:55 +0800 |
---|---|---|
committer | Lin Jen-Shin <godfat@godfat.org> | 2017-11-10 15:33:55 +0800 |
commit | 1f2cdf6297f57fc3d87fe2183a4ee45355a799f1 (patch) | |
tree | edb0654717a74b11bcc7595afc408b0ee0380a01 | |
parent | a655cac283d95f05434fd0b3e4f015474674029e (diff) | |
parent | af60a6ccb7196df571aed3bf6c1d09a072bad157 (diff) | |
download | gitlab-ce-1f2cdf6297f57fc3d87fe2183a4ee45355a799f1.tar.gz |
Merge branch '10-1-stable' into 10-1-stable-patch-2
* 10-1-stable:
Update VERSION to 10.1.2
Update CHANGELOG.md for 10.1.2
Merge branch 'fix-mysql-grant-check' into 'master'
Merge branch '36099-api-responses-missing-x-content-type-options-header' into '10-1-stable'
Merge branch 'ssrf-protections-round-2' into 'security-10-1'
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | lib/api/api.rb | 5 | ||||
-rw-r--r-- | lib/gitlab/database/grant.rb | 30 | ||||
-rw-r--r-- | lib/gitlab/url_blocker.rb | 4 | ||||
-rw-r--r-- | spec/lib/gitlab/database/grant_spec.rb | 22 | ||||
-rw-r--r-- | spec/lib/gitlab/url_blocker_spec.rb | 16 | ||||
-rw-r--r-- | spec/requests/api/projects_spec.rb | 6 | ||||
-rw-r--r-- | spec/support/matchers/security_header_matcher.rb | 5 |
9 files changed, 63 insertions, 31 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e9515c1da9..30ab05164c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 10.1.2 (2017-11-08) + +- [FIXED] Fix TRIGGER checks for MySQL. + ## 10.1.1 (2017-10-31) - [FIXED] Auto Devops kubernetes default namespace is now correctly built out of gitlab project group-name. !14642 (Mircea Danila Dumitrescu) @@ -1 +1 @@ -10.1.1 +10.1.2 diff --git a/lib/api/api.rb b/lib/api/api.rb index 79e55a2f4f7..1664197689d 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -57,7 +57,10 @@ module API mount ::API::V3::Variables end - before { header['X-Frame-Options'] = 'SAMEORIGIN' } + before do + header['X-Frame-Options'] = 'SAMEORIGIN' + header['X-Content-Type-Options'] = 'nosniff' + end # The locale is set to the current user's locale when `current_user` is loaded after { Gitlab::I18n.use_default_locale } diff --git a/lib/gitlab/database/grant.rb b/lib/gitlab/database/grant.rb index aee3981e79a..9f76967fc77 100644 --- a/lib/gitlab/database/grant.rb +++ b/lib/gitlab/database/grant.rb @@ -6,28 +6,36 @@ module Gitlab if Database.postgresql? 'information_schema.role_table_grants' else - 'mysql.user' + 'information_schema.schema_privileges' end - def self.scope_to_current_user - if Database.postgresql? - where('grantee = user') - else - where("CONCAT(User, '@', Host) = current_user()") - end - end - # Returns true if the current user can create and execute triggers on the # given table. def self.create_and_execute_trigger?(table) priv = if Database.postgresql? where(privilege_type: 'TRIGGER', table_name: table) + .where('grantee = user') else - where(Trigger_priv: 'Y') + queries = [ + Grant.select(1) + .from('information_schema.user_privileges') + .where("PRIVILEGE_TYPE = 'SUPER'") + .where("GRANTEE = CONCAT('\\'', REPLACE(CURRENT_USER(), '@', '\\'@\\''), '\\'')"), + + Grant.select(1) + .from('information_schema.schema_privileges') + .where("PRIVILEGE_TYPE = 'TRIGGER'") + .where('TABLE_SCHEMA = ?', Gitlab::Database.database_name) + .where("GRANTEE = CONCAT('\\'', REPLACE(CURRENT_USER(), '@', '\\'@\\''), '\\'')") + ] + + union = SQL::Union.new(queries).to_sql + + Grant.from("(#{union}) privs") end - priv.scope_to_current_user.any? + priv.any? end end end diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb index fee1a127fd7..13150ddab67 100644 --- a/lib/gitlab/url_blocker.rb +++ b/lib/gitlab/url_blocker.rb @@ -22,10 +22,12 @@ module Gitlab return true if blocked_user_or_hostname?(uri.user) return true if blocked_user_or_hostname?(uri.hostname) - server_ips = Resolv.getaddresses(uri.hostname) + server_ips = Addrinfo.getaddrinfo(uri.hostname, 80, nil, :STREAM).map(&:ip_address) return true if (blocked_ips & server_ips).any? rescue Addressable::URI::InvalidURIError return true + rescue SocketError + return false end false diff --git a/spec/lib/gitlab/database/grant_spec.rb b/spec/lib/gitlab/database/grant_spec.rb index 651da3e8476..5ebf3f399b6 100644 --- a/spec/lib/gitlab/database/grant_spec.rb +++ b/spec/lib/gitlab/database/grant_spec.rb @@ -1,16 +1,6 @@ require 'spec_helper' describe Gitlab::Database::Grant do - describe '.scope_to_current_user' do - it 'scopes the relation to the current user' do - user = Gitlab::Database.username - column = Gitlab::Database.postgresql? ? :grantee : :User - names = described_class.scope_to_current_user.pluck(column).uniq - - expect(names).to eq([user]) - end - end - describe '.create_and_execute_trigger' do it 'returns true when the user can create and execute a trigger' do # We assume the DB/user is set up correctly so that triggers can be @@ -18,13 +8,11 @@ describe Gitlab::Database::Grant do expect(described_class.create_and_execute_trigger?('users')).to eq(true) end - it 'returns false when the user can not create and/or execute a trigger' do - allow(described_class).to receive(:scope_to_current_user) - .and_return(described_class.none) - - result = described_class.create_and_execute_trigger?('kittens') - - expect(result).to eq(false) + it 'returns false when the user can not create and/or execute a trigger', :postgresql do + # In case of MySQL the user may have SUPER permissions, making it + # impossible to have `false` returned when running tests; hence we only + # run these tests on PostgreSQL. + expect(described_class.create_and_execute_trigger?('foo')).to eq(false) end end end diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb index f18823b61ef..d9b3c2350b1 100644 --- a/spec/lib/gitlab/url_blocker_spec.rb +++ b/spec/lib/gitlab/url_blocker_spec.rb @@ -20,6 +20,22 @@ describe Gitlab::UrlBlocker do expect(described_class.blocked_url?('https://gitlab.com:25/foo/foo.git')).to be true end + 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 + end + + it 'returns true for alternative version of 127.0.0.1 (0x7f.1)' do + expect(described_class.blocked_url?('https://0x7f.1:65535/foo/foo.git')).to be true + end + + it 'returns true for alternative version of 127.0.0.1 (2130706433)' do + expect(described_class.blocked_url?('https://2130706433:65535/foo/foo.git')).to be true + end + + it 'returns true for alternative version of 127.0.0.1 (127.000.000.001)' do + expect(described_class.blocked_url?('https://127.000.000.001:65535/foo/foo.git')).to be true + end + it 'returns true for a non-alphanumeric hostname' do stub_resolv diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 5964244f8c5..2e3416cb74d 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -50,6 +50,12 @@ describe API::Projects do expect(json_response).to be_an Array expect(json_response.map { |p| p['id'] }).to contain_exactly(*projects.map(&:id)) end + + it 'returns the proper security headers' do + get api('/projects', current_user), filter + + expect(response).to include_security_headers + end end shared_examples_for 'projects response without N + 1 queries' do diff --git a/spec/support/matchers/security_header_matcher.rb b/spec/support/matchers/security_header_matcher.rb new file mode 100644 index 00000000000..f8518d13ebb --- /dev/null +++ b/spec/support/matchers/security_header_matcher.rb @@ -0,0 +1,5 @@ +RSpec::Matchers.define :include_security_headers do |expected| + match do |actual| + expect(actual.headers).to include('X-Content-Type-Options') + end +end |