In this article I will demonstrate how an attacker could craft a malicious Python script to initiate a password reset of a GitLab account by injecting two email addresses in to the password reset of GitLab which could lead to code theft, stealing of comit history and possibly user credentials.
Furthermore this type of account hijacking could be used to initiate more successful Phishing attacks on other users and possibly gaining unauthorised access to other systems.
The vulnerability was caused by a bug in how GitLab handled email verification during password reset. An attacker could provide two email addresses during a password reset request, and the reset code would be sent to both addresses. This allowed the attacker to reset the password of any user, even if they didn't know the user's current password.
Affected Versions:
All instances of GitLab CE/EE using the following versions were vulnerable:
16.1 to 16.1.5
16.2 to 16.2.8
16.3 to 16.3.6
16.4 to 16.4.4
16.5 to 16.5.5
16.6 to 16.6.3
16.7 to 16.7.1
Impact
A successful attack could allow the attacker to control the victim's GitLab account. This could allow the attacker to steal sensitive information, such as source code, commit history, and user credentials. The attacker could also use the compromised account to launch further attacks against other users or systems.
Detailed Technical Explanation
The vulnerability resided within GitLab's POST /users/password API endpoint, which is responsible for a password reset. A pentester exploited a flaw in email address validation, bypassing checks with invalid formats. Upon receiving a password reset request with an attacker-controlled email, GitLab incorrectly generated a reset token and sent it to the invalid address. Attackers then intercept this token and use it with a valid target user's email to initiate a password reset, ultimately hijacking the account.
If we look at the password reset request in GitLab, we can see it is requesting to the /users/password endpoint with authenticity_token (hidden CSRF protection token) and email address as a parameter. If a target provides another secondary email address, a password reset token is also sent to the address.
To test this exploit I accessed a GitLab instance inside a virtual machine. I had to add the hostname to Kali first
$ sudo nano /etc/hosts
I entered the address and saved the text file
I used a fake email account to receive the password reset.
Now we need to prepare the payload
$ touch attacker.py
$ sudo nano attacker.py
The Python script is written in to the text file and saved.
We can now execute the attack with the following command:
$ python3 attacker.py -u http://10.10.3.127:8000 -t victim@mail.gitlab.thm -e attacker@mail.gitlab.thm
The script completes a password reset to Gitlab but gives 2 email addresses. The first is the genuine email address for the Gitlab account and the second email is the attackers email. The code begins by making a POST request to the /users/password/new endpoint to scrap an authenticity token, then it makes another API call to the /users/passwords endpoint with the victim and attacker email addresses.
Now we can login to the attackers email and we will see the password reset email
Once we have specified our password we can login with the victims email and OUR password.
Screenshot showing the admin page of Gitlab
Such vulnerabilities are difficult to identify as legitimate calls to the endpoint will occur.
Examining Logs If we have an SIEM solution that captures weblogs, we can create an alert or use this search query to look for the following possible exploitation attempts:
Check for weblogs for API calls to /users/password with multiple email addresses.
Inspect email server logs for messages from GitLab with unexpected recipients (attacker-controlled emails).
Examine GitLab audit logs for entries containing a value for meta.caller.id as PasswordsController#create.
Mitigation Techniques
As part of mitigation, GitLab has officially released the patch. We can see from the source code review that additional validation and verification steps have been added to the GitLab source code repository for the email address to curtail the possibility of exploitation in the future.
However, it is of paramount importance to see that non-compliance with secure coding practices leads to disastrous results.
So far, we learned how to perform the attack and how to detect the attack patterns in the logs; let's talk about a few mitigation steps that we can take to prevent our servers from being exploited.
Enable GitLab security alerts that would allow early awareness of patches.
Upgrade GitLab to a patched version.
Enable two-factor authentication (2FA) for all GitLab accounts, especially administrator accounts.
Follow secure coding practices, including proper input validation and email address verification.