ESCALATED: Blind SSRF on External Authorization Service
HackerOne report #692159 by xanbanx on 2019-09-11, assigned to hackerjuan:
Hi GitLab Security Team,
Summary
I found a blind SSRF vulnerability on the external authorization server configuration. An attacker can thereby make POST requests to the local network or to any other one on behalf of the GitLab server.
Steps to reproduce
This has been tested on a local installation of GitLab EE 12.3.0-pre d777fa6d.
- Set local listener on, e.g., port 10000:
nc -dklp 10000 -vv - As an administrator, go to
http://example.gitlab.com/admin/application_settings#js-external-auth-settings - Enable and enter the Service URL
http://localhost:10000and save the settings. Don't forget to fill out the default classification label, this this field is required. - Save the settings again to trigger a call authorization server, monitor the POST request and the previously set up listener
- In the user interface you see the error
External authorization service default label is unavailable: read timeout reachedbecause the listener did not respond - On
http://localhost:22you'll get the error messageExternal authorization service default label is unavailable: malformed header (Excon::Error::ResponseParse) - On a not open port you get the error message
External authorization service default label is unavailable: Connection refused - connect(2) for 127.0.0.1:1000 (Errno::ECONNREFUSED)
- In the user interface you see the error
Impact
An attacker can create blind post requests on behalf of the GitLab server including to the local infrastructure. You can easily scan the ports of any network be capturing the response. An administrator, who does not have access to the underlying infrastructure can use this to scan the network to findout how to go forward with an attack.
What is the current bug behavior?
URL input for external authorization accepts local addresses. Furthermore, upon request, the URL is not validated
What is the expected correct behavior?
The service URL should not access local addresses nor the request should perform requests to local networks. After looking to the code, I found that in lib/gitlab/external_authorization/client.rb#20 the POST request is performed using Excon.post() rather than Gitlab::HTTP, which contains all SSRF mitigations.
Relevant logs and/or screenshots
Output of checks
This has been tested on a local installation of GitLab EE 12.3.0-pre d777fa6d
Results of GitLab environment info
System information
System: Ubuntu 18.04
Proxy: no
Current User: xanbanx
Using RVM: no
Ruby Version: 2.6.3p62
Gem Version: 3.0.3
Bundler Version:1.17.2
Rake Version: 12.3.2
Redis Version: 4.0.9
Git Version: 2.23.0
Sidekiq Version:5.2.7
Go Version: go1.12.6 linux/amd64
GitLab information
Version: 12.3.0-pre
Revision: d777fa6dd9f
Directory: /home/xanbanx/gdk/gdk-ee/gitlab
DB Adapter: PostgreSQL
DB Version: 10.10
URL: http://localhost:3001
HTTP Clone URL: http://localhost:3001/some-group/some-project.git
SSH Clone URL: ssh://xanbanx@localhost:2222/some-group/some-project.git
Elasticsearch: no
Geo: no
Using LDAP: no
Using Omniauth: yes
Omniauth Providers:
GitLab Shell
Version: 10.0.0
Repository storage paths:
- default: /home/xanbanx/gdk/gdk-ee/repositories
GitLab Shell path: /home/xanbanx/gdk/gdk-ee/gitlab-shell
Git: /usr/bin/git
Best regards,
Xanbanx
Impact
See above.