GraphQL leaks numbers of vulnerabilities to unauthorized users
HackerOne report #880944 by xanbanx
on 2020-05-22, assigned to @vdesousa:
Hi GitLab Security Team,
Summary
GitLab recently implemented a new GraphQL API to list all vulnerabilities (SAST, DAST,...).
A smaller API just returns the counts of unfixed vulnerabilities.
This API, however, is missing permission checks. So anyone, who has access to the project, i.e., anyone to a public project, can read the numbers of unfixed vulnerabilities. I think this one is one of the rare cases where numbers leaking are in scope of the H1 policy, and I also provide a git patch fixing the issue :D
Steps to reproduce
- Create a public project, e.g., named
test-vulnerabilities
, and enable GitLab CI - Add the attached
gl-sast-report.json
file to the root directory of the repository - Add the following
.gitlab-ci.yml
file to the repository
test:
script:
- echo "Hello World"
artifacts:
reports:
sast: gl-sast-report.json
- As an unauthenticated user, visit
https://gitlab.example.com/-/graphql-explorer
and perform the following graphql query:
{
project(fullPath:"root/test-vulnerabilities") {
name
vulnerabilitySeveritiesCount {
critical
high
medium
low
info
unknown
}
}
}
This now returns the number of unfixed vulnerabilities for all severities.
{
"data": {
"currentUser": null,
"project": {
"name": "test-vulnerabilities",
"vulnerabilitySeveritiesCount": {
"critical": 1,
"high": 1,
"medium": 10,
"low": 17,
"info": 0,
"unknown": 4
}
}
}
}
In the example above, I used a public project and an unauthenticated user.
The vulnerability however exists also in other permission models, e.g., private project and guest user,...
The same query also works on the gitlab-org/gitlab
repository, which returns the following vulnerability counts for an unauthenticated user:
{
"data": {
"project": {
"name": "GitLab",
"vulnerabilitySeveritiesCount": {
"critical": 1,
"high": 2,
"medium": 3,
"low": 1,
"info": 0,
"unknown": 2302
}
}
}
}
Impact
Graphql API leaks the number of unfixed vulnerabilities to unauthorized users. Since this is leaking that there are unfixed vulnerabilities, e.g., a critical one, I think this report about numbers is in scope of GitLab's H1 policy.
What is the current bug behavior?
Graphql API leaks the number of unfixed vulnerabilities to unauthorized.
What is the expected correct behavior?
Graphql only returns the number of unfixed vulnerabilities if the user has access to view vulnerabilities.
I think the fix for that is pretty simple. The GraphQL vulnerability count type is missing a permission check.
I think the following patch should fix that.
From e6258f63f252eb773d864964019573f41c174309 Mon Sep 17 00:00:00 2001
From: Xanbanx <xanbanx@wearehackerone.com>
Date: Sun, 5 Apr 2020 21:34:18 +0200
Subject: [PATCH 1/1] Add permission check to Graphql vulnerability counts
---
ee/app/graphql/types/vulnerability_severities_count_type.rb | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ee/app/graphql/types/vulnerability_severities_count_type.rb b/ee/app/graphql/types/vulnerability_severities_count_type.rb
index 75ee10fe69a..4b1ebc900f7 100644
--- a/ee/app/graphql/types/vulnerability_severities_count_type.rb
+++ b/ee/app/graphql/types/vulnerability_severities_count_type.rb
@@ -6,6 +6,8 @@ module Types
graphql_name 'VulnerabilitySeveritiesCount'
description 'Represents vulnerability counts by severity'
+ authorize :read_vulnerability
+
::Vulnerabilities::Occurrence::SEVERITY_LEVELS.keys.each do |severity|
field severity, GraphQL::INT_TYPE, null: true,
description: "Number of vulnerabilities of #{severity.upcase} severity of the project"
--
2.25.1
Output of checks
This bug happens on GitLab.com, running on GitLab Enterprise Edition 13.0.0-pre 9854ff0f.
Best regards,
Xanbanx
Impact
See above.
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
Potential solution
If the blocking issue gets merged
-
backend Implement
self.visible?(context)
onTypes::VulnerabilitySeveritiesCountType
(ee/app/graphql/types/vulnerability_severities_count_type.rb
) as per https://graphql-ruby.org/authorization/visibility
If the blocking issue doesn't get merged
- backend Apply workaround from !31678 (comment 350456537)