Commiting directories containing LF character results in 500 errors in Web UI when viewing commit
HackerOne report #1937213 by cryptopone
on 2023-04-06, assigned to @ottilia_westerlund:
Report | Attachments | How To Reproduce
Report
Summary
An attacker is able to add new directories containing the line feed character (%0a
or \n
). Once committed to a repository, attempting to view the details of the commit via the GitLab website will result in various 500 Internal Server Errors. Some of these activities include:
- Viewing changes inside of a merge request containing the malicious directory
- Viewing the malicious directory in the project/repository file browser
- Viewing the commit details containing the malicious directory
- Comparing branch revisions when one of the branches contain the malicious directory
Steps to reproduce
Note: Two accounts will be needed (Attacker and Victim).
Prerequisites (Victim Account):
- Have the victim user log in and navigate to (http://gitlab.example.com/projects/new).
- Create a new project (VictimProject) with
Internal
visibility andInitialize repository with a README
checked. - Navigate to the project members page (http://gitlab.example.com/victim/victimproject/-/project_members) and use
Invite members
to invite the attacker as a developer for the project.
Reproduction Steps (Attacker with BurpSuite):
- Have the attacker login, navigate to the VictimProject and create a new branch called
AttackerBranch
(via http://gitlab.example.com/victim/victimproject/-/branches/new). - The attacker will be redirected to http://gitlab.example.com/victim/victimproject/-/tree/AttackerBranch
- Click the
+
dropdown button and selectNew file
(redirects to http://gitlab.example.com/victim/victimproject/-/new/AttackerBranch/). - In BurpSuite use the Proxy -> Intercept tab and ensure
Intercept is on
is set. - Set the file name to
beforeafter/beforeafter/hiddenfile.txt
. For the file contents put inHidden attacker contents.
. Target branch should beAttackerBranch
. - Press the
Commit changes
button and have BurpSuite intercept the POST request. - The POST request will use a url encoded body. Change the
file_name
from:
file_name=beforeafter%2Fbeforeafter%2Fhiddenfile.txt
by adding %0a
between before
and after
for the two directories:
file_name=before%0aafter%2Fbefore%0aafter%2Fhiddenfile.txt
- Forward the request to the server. Intercept can also be turned off at this point.
- The page will reload and if done successfully you'll see a new message
"before after/before after/hiddenfile.txt" did not exist on "AttackerBranch"
and the commit message area will display a loading indicator. - If you press F12 to open Developer Tools and access the console you will also see several 500 errors.
- Have the attacker create a new merge request by clicking the
Create merge request
in the green messageYou pushed to AttackerBranch just now
(or by navigating to http://gitlab.example.com/victim/victimproject/-/merge_requests/new?merge_request%5Bsource_branch%5D=AttackerBranch). Then clickCreate merge request
at the bottom of the page.
Reproduction Steps (Victim):
- Navigate to the merge request created by the attacker (http://gitlab.example.com/victim/victimproject/-/merge_requests/1).
- Click on the
Changes
tab to view the changes but note theError: Couldn't load some or all of the changes.
error message. - Try clicking on the commits tab, then on
Add new file
to view the commit changes and again onAdd new file
and note the resulting 500 error.
At this point the web UI will throw 500 Internal Server Errors on a variety of tasks, as seen when attempting to view the merge request changes:
- Compare Revisions (between AttackerBranch and main) - http://gitlab.example.com/victim/victimproject/-/compare?from=main&to=AttackerBranch when clicking the
Compare
button. - Attempting to view the AttackerBranch and clicking on the
before after
directory to view its contents (http://gitlab.example.com/victim/victimproject/-/tree/AttackerBranch)
Impact
An attacker could disrupt regular processes such as reviewing merge requests or viewing portions of a project via the web UI.
My initial report uses the following reasoning for the CVSS score:
AC:L
: Attacker can use the web UI to add a directory and modify the POST request before it reaches the server.
PR:L
: Attacker requires an authenticated account but does not require elevated roles within a project.
UI:N
: Attack can be accomplished without any user interaction.
S:U
: Impact is localized to the exploitable component.
C:N
: No confidential information is disclosed.
I:N
: No integrity loss.
A:L
: The commit details cannot be viewed in the Web UI but could still be reviewed using a local git repo.
Examples
Attached is a copy of the project I created on my self-hosted instance running 15.10.2 following these repro steps. It's possible to import this project file as a "GitLab Export" to see the merge request and resulting 500 errors.
directories_with_lf_victim_victimproject_export.tar.gz
Additionally, I created a project on GitLab.com and setup a similar project (though I only used a single account) to demonstrate the 500 errors as well. The project is currently Private but please let me know if you would like access.
https://gitlab.com/Cryptopone/crlf-directory-repro/-/tree/AttackerBranch?ref_type=heads
What is the current bug behavior?
If a directory containing a line feed character is committed to a project's repository, the web UI will throw a 500 Internal Server Error when any attempts are made to view the contents of the commit.
What is the expected correct behavior?
The web page should be displayed normally, without throwing a 500 error.
Relevant logs and/or screenshots
Attacker adds linefeed characters to the directory paths to the hidden file:
Response when attacker pushes the malicious directories and hidden file to the project repo:
Victim attempting to view changes inside of a merge request:
==> /var/log/gitlab/gitlab-rails/production.log <==
Gitlab::Git::CommandError (13:error streaming commits: cat-file get commit "6280e1a0a6ffab99ab5ea8b9ff21ea442fa953a1": object not found.):
lib/gitlab/git/wraps_gitaly_errors.rb:15:in `rescue in wrapped_gitaly_errors'
lib/gitlab/git/wraps_gitaly_errors.rb:6:in `wrapped_gitaly_errors'
lib/gitlab/git/repository.rb:377:in `log'
lib/gitlab/git/commit.rb:47:in `where'
app/models/repository.rb:168:in `commits'
lib/gitlab/code_navigation_path.rb:28:in `block in build'
lib/gitlab/utils/strong_memoize.rb:34:in `strong_memoize'
lib/gitlab/code_navigation_path.rb:26:in `build'
lib/gitlab/code_navigation_path.rb:16:in `full_json_path_for'
app/serializers/diff_file_entity.rb:66:in `block in <class:DiffFileEntity>'
<trimmed>
Victim attempting to compare revisions:
==> /var/log/gitlab/gitlab-rails/production.log <==
ActionView::Template::Error (undefined method `lines' for nil:NilClass):
1: - diff_file = viewer.diff_file
2: - blob = diff_file.blob
3: - total_lines = blob.lines.size
4: - total_lines -= 1 if total_lines > 0 && blob.lines.last.blank?
5: - if diff_view == :parallel
6: = render "projects/diffs/parallel_view", diff_file: diff_file, total_lines: total_lines
app/views/projects/diffs/viewers/_text.html.haml:3
app/views/projects/diffs/_viewer.html.haml:14
app/views/projects/diffs/_content.html.haml:11
app/views/projects/diffs/_file.html.haml:42
app/views/projects/diffs/_diffs.html.haml:39
app/views/projects/compare/show.html.haml:12
app/controllers/application_controller.rb:142:in `render'
app/controllers/projects/compare_controller.rb:37:in `show'
<trimmed>
Attempting to view the project repository or navigating into one of the malicious folders:
==> /var/log/gitlab/gitlab-rails/production.log <==
Gitlab::Git::CommandError (13:error streaming commits: cat-file get commit "035a86f727a8236a721ae4bccdd22ce1a5b54be5": object not found.):
lib/gitlab/git/wraps_gitaly_errors.rb:15:in `rescue in wrapped_gitaly_errors'
lib/gitlab/git/wraps_gitaly_errors.rb:6:in `wrapped_gitaly_errors'
lib/gitlab/git/repository.rb:377:in `log'
lib/gitlab/git/commit.rb:47:in `where'
lib/gitlab/git/commit.rb:97:in `last_for_path'
app/graphql/resolvers/last_commit_resolver.rb:14:in `resolve'
lib/gitlab/graphql/present/field_extension.rb:18:in `resolve'
lib/gitlab/graphql/tracers/timer_tracer.rb:20:in `trace'
<trimmed>
Output of checks
This bug happens on GitLab.com
Results of GitLab environment info
System information
System:
Proxy: no
Current User: git
Using RVM: no
Ruby Version: 3.0.5p211
Gem Version: 3.2.33
Bundler Version:2.3.15
Rake Version: 13.0.6
Redis Version: 6.2.11
Sidekiq Version:6.5.7
Go Version: unknown
GitLab information
Version: 15.10.2-ee
Revision: a54d6973eae
Directory: /opt/gitlab/embedded/service/gitlab-rails
DB Adapter: PostgreSQL
DB Version: 13.8
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.18.0
Repository storages:
- default: unix:/var/opt/gitlab/gitaly/gitaly.socket
GitLab Shell path: /opt/gitlab/embedded/service/gitlab-shell
Impact
Impact
An attacker could disrupt regular processes such as reviewing merge requests or viewing portions of a project via the web UI.
My initial report uses the following reasoning for the CVSS score:
AC:L
: Attacker can use the web UI to add a directory and modify the POST request before it reaches the server.
PR:L
: Attacker requires an authenticated account but does not require elevated roles within a project.
UI:N
: Attack can be accomplished without any user interaction.
S:U
: Impact is localized to the exploitable component.
C:N
: No confidential information is disclosed.
I:N
: No integrity loss.
A:L
: The commit details cannot be viewed in the Web UI but could still be reviewed using a local git repo.
Attachments
Warning: Attachments received through HackerOne, please exercise caution!
- directories_with_lf_victim_victimproject_export.tar.gz
- AttackerAddsLFtoDirectoriesFilePath.png
- AfterAttackerPushesFileToRepo.png
- VictimViewingMergeRequestChanges.png
- VictimAttemptingToCompareAttackerBranchWithMain.png
- VictimAttemptingToBrowseLFDirectory.png
How To Reproduce
Please add reproducibility information to this section: