Short SHA Attack and other problems in Commit Blob -- Forked Private Project's Source Code Disclosure
HackerOne report #633358 by ngalog
on 2019-07-01, assigned to gitlab_cmaxim
:
Summary
There is an interesting feature in Gitlab, if a project is forked to another project, the merge request commit blob of the forked project will be viewable from the original project. And I observed there are three problems in this feature: (Could be difficult to understand without example, you can come back after seeing the example)
- Once someone got knowledge to the commit sha value, there is no authorisation check against the MR commit page. i.e. Unauthorised users could view private project's commit source code from the original project page --> more on this in example
- The SHA value being used in the MR commit url, e.g. https://gitlab.com/goldngalog3/open-source-but-mr-is-private/blob/b2864d9d2a07d233be3f3877935a076d4a013cd4 could be shorten to four characters only, i.e. https://gitlab.com/goldngalog3/open-source-but-mr-is-private/blob/b286 -- and it is still valid
- The MR commit url, is vulnerable to CSRF attack. Normally, the commit url will not be shown in the original project if there is no MR from the forked project. However, I found that the commit url will be shown in the original project after a GET request is made from the user with proper permission from the forked project.
Steps to reproduce and Example:
https://gitlab.com/goldngalog3/open-source-but-mr-is-private --> original project
https://gitlab.com/ashleyjohnson/open-source-but-mr-is-private --> forked project fork from goldngalog3/open-source-but-mr-is-private
The settings for goldngalog3/open-source-but-mr-is-private
is that it has public repo, but private MR permission, i.e. public user/anonymous user should not be able to view any of MR source code
The settings for ashleyjohnson/open-source-but-mr-is-private
is that it is a private project, and is forked from goldngalog3/open-source-but-mr-is-private
and it is able to open MR in goldngalog3/open-source-but-mr-is-private
I have already opened a MR from ashleyjohnson/open-source-but-mr-is-private
to goldngalog3/open-source-but-mr-is-private
. So as an anonymous user, you should not be able to view the MR details not to mention the source code for the MR.
However you can still see the MR source code that belongs to ashleyjohnson/open-source-but-mr-is-private
in this link https://gitlab.com/goldngalog3/open-source-but-mr-is-private/tree/b2864d9d2a07d233be3f3877935a076d4a013cd4 --> Problem 1 I mentioned above
What makes it even more interesting is that, if you visit https://gitlab.com/goldngalog3/open-source-but-mr-is-private/tree/b286 , you can still see the same thing, i.e. short SHA --> Problem 2 I mentioned above
And about problem 3, it needs some steps to verify from your side. You can verifiy using a forked project, as an owner of the forked project, visit this link with path_of_forked_project
, id_of_forked_project
and id_of_original_project
replaced
https://gitlab.com/:path_of_forked_project/merge_requests/new/diffs?utf8=%E2%9C%93&merge_request%5Bsource_project_id%5D=:id_of_forked_project&merge_request%5Bsource_branch%5D=master&merge_request%5Btarget_project_id%5D=:id_of_original_project&merge_request%5Btarget_branch%5D=master
And without doing anything else, i.e. pretending you are being csrf attacked, you should be able to see your forked project source code in https://gitlab.com/:path_of_original_project/tree/:commit_sha_of_your_master_ref_forked_project
Conclusion
- Commit SHA of private project is not checking for proper authorisation so that you can see the source code from private forked project as in this link
- Commit SHA of private project is vulnerable to short sha attack, so that you can see the source code using a very short sha, just 4 characters are enough, as in this link https://gitlab.com/goldngalog3/open-source-but-mr-is-private/tree/b286
- Commi SHA of private project will be created in the source project with a CSRF attack as shown above.
Impact
Private project source code could be stolen using the above problems in two steps for the scenario that the original project is public but the forked project is private:
- Send CSRF attack to the private proejct owner as described above
- Brute force that 4 characters of SHA commit in https://gitlab.com/:original_project_with_public_repo/tree/:brute_force_here -- possible characters are abcdef1234567890, there are only 65535 possibilities for four characters, brute force could finish in one hour or less with different IP addresses.