2019 Q1 Recurity Assessment: Open Redirect
https://gitlab.com/gitlab-com/gl-security/engineering/issues/329
Details
Within the Oauth/:GeoAuthController
for the secondary Geo node, a redirect is triggered after successful authentication. The redirect target is designated by th login_state in ee/app/controllers/oauth/geo_auth_controller.rb
as follows:
def after_sign_in_with_gitlab(token)
session[:access_token] = token
# Prevent alert from popping up on the first page shown after authentication.
flash[:alert] = nil
redirect_to(login_state.return_to /| root_path)
end
The login_state
is comprised of a salt, the redirect URL and an HMAC over the redirect URL (see also chapters 3.1 and 3.2). Furthermore, the login_state
value will be used as a state parameter within the OAuth flow for login to the secondary
note (see chapter 3.4). The initial generation of the state parameter is taking place upon a GET request towards /users/sign_in
on the secondary node. The open redirect issue results from the fact that a tampered HOST header will be reflected in the login_state
's redirect target. The secondary node will redirect to arbitrary hosts when an attacker mounts a CSRF attack using such a pre-generated state parameter (see also chapter 3.4).
Reproduction Steps
The following curl
command can be utilized to verify the issue:
curl https://secondary.recurity.gogitlab.com/users/sign_in -H 'Host: this.is.not.my.host'
The redirect target can be observed in the state parameter below:
<html><body>You are being <a href="https://this.is.not.my.host/oauth/geo/auth?
state=c16d2268f8f25667%3A771b6d0015a023f9ec6746b9e00bbbd49587aa5285babf77c73e5fda1d
af9d8c%3Ahttps%3A%2F%2Fthis.is.not.my.host%2F">redirected</a>.</body></html>
Also note that, if the HOST header is not spoofable, the X-Forwarded-Host header might be utilized as well. Both vectors were available on the test environment.
Recommendation
This issue can be mitigated in two different places. First, the application should not generate redirect targets for other hosts. Second, the input to redirect_to
should be sanitized in a way that no other hosts can be supplied as a target. Recurity Labs is in favor of implementing both mitigation approaches as they do not exclude each other.