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:

  1. 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.
  2. Create 2 accounts on the Idp (Okta). One will be the attacker's account, and the second one is the victim's.
  3. 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.
  4. 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)
  5. 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.
  6. 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.
  7. 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!

  • saml.html
Edited Jun 26, 2019 by Alexander Dietrich
Assignee Loading
Time tracking Loading