Taking over Gitlab accounts when SAML is configured
HackerOne report #471323 by mishre on 2018-12-23, assigned to jritchey:
Summary:
Due to an incorrect SAML callback implementation an attacker can, in certain circumstances take over a victim's account, when the installed Gitlab instance supports SAML authentication by making a victim browsing the attacker's website.
Description:
When SAML is supported on the installed Gitlab instance, users can login using an SSO provider such as Okta that can be setup by following the instructions here: https://docs.gitlab.com/ee/administration/auth/okta.html. However, due to a vulnerability on the SAML callback endpoint, it is possible for an attacker to connect the attacker's Okta (or any other configured Idp account) to the victim's Gitlab account practically taking over the victim's account. In order to exploit this vulnerability the attacker needs to construct a web page which upon browsing sends a POST request to the https://gitlab-instance/users/auth/saml/callback endpoint containing a valid SAMLResponse parameter (which identifies the attacker). I have attached a poc web page.
Steps To Reproduce:
- Setup the Gitlab instance to support SAML, I have used Okta as a provided by following the instructions here: https://docs.gitlab.com/ee/administration/auth/okta.html.
- Create 2 accounts on the Idp (Okta). One will be the attacker's account, and the second one is the victim's.
- Create an account on Gitlab using the regular registration process for the victim (Do not use the SAML-based registration) and login to this account - this is the victim's account.
- As the attacker start the sign-in to Gitlab via SAML process while intercepting the request and drop the request when arriving back to https://gitlab-instance/users/auth/saml/callback (while saving the parameter values for later usage)
- Download the attached poc file, and change the poc form's SAMLResponse parameter to the one you have saved on step4, and the RelayState also to the one saved on step4, while also changing the url on the poc to be your instance's url.
- While being logged in to Gitlab with the normally registered user (not via SAML), browse the poc. That account should now be connected to the attacker's account.
- Make sure that you can now login to the victim's account by logging in via SAML.
Root cause
The issue probably also affects the Kerberos and CAS3 integrations since these are the 3 integration for which CSRF checks are disabled( https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/controllers/omniauth_callbacks_controller.rb#L7):
protect_from_forgery except: [:kerberos, :saml, :cas3], prepend: true
Even if the CSRF check is disabled this would not be an issue, if there was no automatic pairing of the logged in account to the SAML identity here (https://gitlab.com/gitlab-org/gitlab-ce/blob/master/app/controllers/omniauth_callbacks_controller.rb#L77):
def omniauth_flow(auth_module, identity_linker: nil)
if current_user
log_audit_event(current_user, with: oauth['provider'])
identity_linker ||= auth_module::IdentityLinker.new(current_user, oauth)
identity_linker.link
if identity_linker.changed?
redirect_identity_linked
elsif identity_linker.failed?
redirect_identity_link_failed(identity_linker.error_message)
else
redirect_identity_exists
end
else
sign_in_user_flow(auth_module::User)
end
end
You can see in the code that if there is a "current_user" active, an automatic pairing will occur without any prompt or verification from the user's side that he approves such pairing.
Impact
On any SAML configured Gitlab instance (potentially also on Kerberos and Cas3 instances as well) an attacker can gain complete control over victims accounts by making them click on a single link.
Attachments
Warning: Attachments received through HackerOne, please exercise caution!