Endless Redirect Loop in any project when "format" parameter is set to "git" value
HackerOne report #2936949 by sim4n6
on 2025-01-14, assigned to @ngeorge1:
Report | Attachments | How To Reproduce
Report
Summary
I noticed an endless redirect loop is possible in any project when the parameter "format" is set to git. So, clicking on a URL in the form of :
http://gitlab.example.com/root/testproject?format=git
It would perform an endless number of redirects of 302.
A curl would also be enough:
Steps to reproduce
- Set up a gitlab instance on for instance gitlab.example.com
- Create a public project
testproject
on the user's namespacetester1
. - Click on the following URL http://gitlab.example.com/tester1/testproject?format=git
Notice the redirect of a GET request to /tester1/testproject?format=git to the same location.
Impact
mentioned below.
Examples
(If the bug is project-related, please create an example project and export it using the project export feature)
any created project would be affected.
(If you are using an older version of GitLab, this will also help determine whether the bug has been fixed in a more recent version)
Used the latest stable release: v17.7.1-ee
(If the bug can be reproduced on GitLab.com without violating the Rules of Engagement
as outlined in the program policy, please provide the full path to the project.)
did not try there.
What is the current bug behavior?
(What actually happens, include relevant screenshots, API results, or complete HTTP requests)
There is an endless number of redirects.
What is the expected correct behavior?
(What you should see instead, include relevant screenshots, API results, or complete HTTP requests)
The issue comes from the way the function redirect_git_extension()
is used in lines master/app/controllers/projects_controller.rb#L564-L577.
# Redirect from localhost/group/project.git to localhost/group/project
def redirect_git_extension
return unless params[:format] == 'git'
# `project` calls `find_routable!`, so this will trigger the usual not-found
# behaviour when the user isn't authorized to see the project
return if project.nil? || performed?
uri = URI(request.original_url)
# Strip the '.git' part from the path
uri.path = uri.path.sub(%r{\.git/?\Z}, '')
redirect_to(uri.to_s)
end
The function does not check if the URL requested does contain a path with .git
when the parameter "format" equals git
.
One way of fixing this is to perform another check request.path.include?('.git')
to avoid such a behavior.
Relevant logs and/or screenshots
(Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it's very hard to read otherwise.)
Output of checks
(If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com)
did not try there, it is not permitted to test Denial of service issues on gitlab.com. But that would be easy you need to click on a URL as https://gitlab.com/namespace_id/project_id?format=git
Results of GitLab environment info
(For installations with omnibus-gitlab package run and paste the output of:
sudo gitlab-rake gitlab:env:info
)
(For installations from source run and paste the output of:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
)
System information
System: Ubuntu 24.10
Proxy: no
Current User: git
Using RVM: no
Ruby Version: 3.2.5
Gem Version: 3.5.23
Bundler Version:2.5.11
Rake Version: 13.0.6
Redis Version: 7.0.15
Sidekiq Version:7.2.4
Go Version: unknown
GitLab information
Version: 17.7.1-ee
Revision: 3c8f631cd0a
Directory: /opt/gitlab/embedded/service/gitlab-rails
DB Adapter: PostgreSQL
DB Version: 14.11
URL: http://gitlab.example.com
HTTP Clone URL: http://gitlab.example.com/some-group/some-project.git
SSH Clone URL: git@gitlab.example.com:some-group/some-project.git
Elasticsearch: no
Geo: no
Using LDAP: no
Using Omniauth: yes
Omniauth Providers:
GitLab Shell
Version: 14.39.0
Repository storages:
- default: unix:/var/opt/gitlab/gitaly/gitaly.socket
GitLab Shell path: /opt/gitlab/embedded/service/gitlab-shell
Gitaly
- default Address: unix:/var/opt/gitlab/gitaly/gitaly.socket
- default Version: 17.7.1
- default Git Version: 2.47.0
Impact
An endless number of redirects on the victim's client side.
This one sits to be leveraged for more advanced denial of service and may cause further damage to SEO for instance, a search bot would lower the rating of a website if such an issue is triggered.
I am also aware that most modern browsers have a protection mechanism for such an issue with an NS_ERROR_REDIRECT_LOOP
error, so I am setting the availability to low for such an issue.
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
How To Reproduce
Please add reproducibility information to this section: