CVE-2026-5524: Verified Repro With Script Download
CVE-2026-5524: Divi Form Builder WordPress plugin allows unauthenticated arbitrary file upload via user-controlled acceptFileTypes, leading to RCE by uploading executable PHP extensions and accessing them in /wp-content/uploads/de fb uploads/.
CVE-2026-5524 is verified against divi-form-builder · wordpress. Affected versions: All versions up to and including 5.1.8. Vulnerability class: RCE. This critical reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00252.
What Is CVE-2026-5524?
CVE-2026-5524 is a critical unrestricted file upload vulnerability (CWE-434) in the Divi Form Builder WordPress plugin that lets an unauthenticated attacker upload and execute arbitrary PHP files, resulting in remote code execution. Pruva reproduced it (reproduction REPRO-2026-00252).
CVE-2026-5524 Severity & CVSS Score
CVE-2026-5524 is rated critical severity, with a CVSS base score of 9.8 out of 10.
Critical — the most severe class — typically remotely exploitable with severe impact. Treat as an emergency.
Affected divi-form-builder Versions
divi-form-builder · wordpress versions All versions up to and including 5.1.8 are affected.
How to Reproduce CVE-2026-5524
pruva-verify REPRO-2026-00252 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00252/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-5524
- reached the target end-to-end
- full exploit chain demonstrated
- on the real production code path
- high confidence
- the upstream fix blocks the same trigger
acceptFileTypes POST parameter set to phtml|phar|php5|php7 and uploaded .phtml payload content
- POST /wp-admin/admin-ajax.php action=de_fb_image_upload
- do_image_upload(); GET /wp-content/uploads/de_fb_uploads/*.phtml
How the agent worked
Root Cause and Exploit Chain for CVE-2026-5524
- Affected versions: The ticket claims all versions up to and including 5.1.8. This run reproduced the issue against an original Divi Form Builder v5.1.2 plugin archive (
sha256=85bf508b12f6d6152f06f8c5eb3143963c3446a7338e90e1de180f5da8a51c34). - Risk level and consequences: Critical. The vulnerable path is reachable by unauthenticated HTTP requests with a valid public form nonce. Successful exploitation allows arbitrary PHP payload upload and web request execution as the Apache/PHP user (
www-datain this reproduction), which is remote code execution.
Impact Parity
- Disclosed/claimed maximum impact: Remote code execution via unauthenticated arbitrary file upload.
- Reproduced impact from this run: Full PHP code execution through the live WordPress/Apache product path. The uploaded
.phtmlpayload executed and returneduid=33(www-data) gid=33(www-data) groups=33(www-data)fromsystem('id'). - Parity:
full. - Not demonstrated: No post-exploitation persistence or privilege escalation beyond the web-server user was attempted; this is not needed to prove the claimed RCE impact.
Root Cause
The original plugin registers the public AJAX upload action to do_image_upload():
includes/classes/init.class.phpregisterswp_ajax_de_fb_image_uploadandwp_ajax_nopriv_de_fb_image_uploadtodo_image_upload().do_image_upload()reads$_POST['acceptFileTypes']and constructs upload validation options as'/\.(' . $accept_file_types . ')$/i'.includes/de_fb_file_upload.phpvalidates the uploaded filename withpreg_match($this->options['accept_file_types'], $file->name), then writes the file towp-content/uploads/de_fb_uploads/and returns a public URL.
Because the extension allow-list comes from the request, the attacker controls the server-side validation pattern. Supplying phtml|phar|php5|php7 makes .phtml pass validation. In the tested Apache/PHP environment, .phtml is handled by PHP, so requesting /wp-content/uploads/de_fb_uploads/payload.phtml executes the attacker-controlled payload. The plugin’s upload-directory protection is insufficient for this class of extension bypass and is also server dependent.
No upstream fixed commit was provided in the ticket. For the negative control, reproduction_steps.sh applies a line-accurate local hardening patch over the same original plugin tree so that do_image_upload() rejects executable extension values before constructing the upload handler options. The patched control returns {"success":false,"data":{"message":"Executable file types are not allowed."}} and the corresponding uploaded URL is absent/404.
Reproduction Steps
- Run
bundle/repro/reproduction_steps.shfrom the bundle root (or setPRUVA_ROOTto the bundle path). - The script installs/starts a real WordPress stack with Apache, mod_php, and MariaDB, installs the original Divi Form Builder v5.1.2 plugin archive, creates a public page containing a form nonce, and sends unauthenticated multipart POST requests to
/wp-admin/admin-ajax.phpwithaction=de_fb_image_upload,fb_nonce, attacker-controlledacceptFileTypes, and a.phtmlpayload. - It performs two vulnerable attempts and then swaps in a patched copy of the same original plugin tree for two fixed negative-control attempts.
- Expected evidence: vulnerable attempts return an upload JSON object containing
/wp-content/uploads/de_fb_uploads/payload_vuln_*.phtml; subsequent GET requests to those URLs execute PHP and return the marker plusidoutput. Fixed attempts return the JSON rejection message and the payload URL returns 404/no marker.
Evidence
- Main run log:
bundle/logs/reproduction_steps.log - Runtime manifest:
bundle/repro/runtime_manifest.json - Original source identity:
bundle/logs/source_identity.txt - Vulnerable attempt artifacts:
bundle/logs/vuln_attempt_1/upload_response.jsonbundle/logs/vuln_attempt_1/execution_response.txtbundle/logs/vuln_attempt_1/result.jsonbundle/logs/vuln_attempt_2/upload_response.jsonbundle/logs/vuln_attempt_2/execution_response.txtbundle/logs/vuln_attempt_2/result.json
- Fixed negative-control artifacts:
bundle/logs/fixed_attempt_1/upload_response.jsonbundle/logs/fixed_attempt_1/execution_response.txtbundle/logs/fixed_attempt_1/result.jsonbundle/logs/fixed_attempt_2/upload_response.jsonbundle/logs/fixed_attempt_2/execution_response.txtbundle/logs/fixed_attempt_2/result.json
- Patch used for negative control:
bundle/logs/fixed_patch.diff - HTTP server evidence:
bundle/logs/apache_access.log,bundle/logs/apache_error.log
Key vulnerable evidence excerpt from bundle/logs/vuln_attempt_1/result.json:
{
"upload_http_code": "200",
"execution_http_code": "200",
"uploaded_or_accepted": true,
"rce_observed": true,
"execution_response_excerpt": "PRUVA_DFB_RCE_MARKER=PRUVA_CVE_2026_5524_vuln_1\nPHP_EXECUTED_AS=www-data\nCMD_OUTPUT_BEGIN\nuid=33(www-data) gid=33(www-data) groups=33(www-data)\n\nCMD_OUTPUT_END\n"
}
Key fixed-control evidence excerpt from bundle/logs/fixed_attempt_1/result.json:
{
"upload_http_code": "200",
"execution_http_code": "404",
"uploaded_or_accepted": false,
"rce_observed": false,
"upload_response_excerpt": "{\"success\":false,\"data\":{\"message\":\"Executable file types are not allowed.\"}}",
"server_marker": "(no marker)"
}
The runtime manifest confirms the API surface was exercised:
{
"entrypoint_kind": "api_remote",
"service_started": true,
"healthcheck_passed": true,
"target_path_reached": true
}
Recommendations / Next Steps
- Do not accept a file-extension allow-list from the client. Treat UI-supplied accepted file types as advisory only; server-side validation must use a trusted form configuration stored server-side.
- Explicitly reject all executable PHP extensions and other server-executable types regardless of the client-supplied field configuration.
- Store uploads in a non-executable location, or serve them through a controlled download endpoint rather than directly from the web root.
- Harden web-server configuration for upload directories on Apache and Nginx; do not rely only on
.htaccessrules because Nginx ignores them and extension mappings differ by server. - Add regression tests that POST to
admin-ajax.php?action=de_fb_image_uploadwith executable extensions (.php,.phtml,.phar,.php5,.php7) and assert that all are rejected and no public executable file is written. - Upgrade to a vendor-fixed release once available and verify that the fix covers both validation and upload-directory execution controls.
Additional Notes
- The script was run successfully twice consecutively after correcting setup and Apache cache behavior.
- The previous rejected surrogate-plugin approach was replaced with an original Divi Form Builder v5.1.2 plugin archive and the real WordPress AJAX endpoint.
- The AJAX action name is
de_fb_image_upload; the original product maps that action to the requesteddo_image_upload()method through WordPresswp_ajax_*hooks. - The negative control is a local patch over the same original project path because the ticket did not provide a fixed commit hash or official patched archive.
CVE-2026-5524 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
Artifacts and Evidence for CVE-2026-5524
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-5524
FAQ: CVE-2026-5524
How does the CVE-2026-5524 file upload exploit work?
acceptFileTypes=phtml|phar|php5|php7 to bypass the intended file-type restriction and uploads a .phtml file into /wp-content/uploads/de_fb_uploads/. Because .htaccess-based PHP blocking (which only blocks .php) is ineffective against these extensions, and Nginx ignores .htaccess entirely, requesting the uploaded file over HTTP executes it as PHP under the web-server user.Which Divi Form Builder versions are affected by CVE-2026-5524?
How severe is CVE-2026-5524?
How can I reproduce CVE-2026-5524?
.phtml payload via de_fb_image_upload with a manipulated acceptFileTypes parameter, and requests the uploaded file over HTTP to demonstrate PHP code execution.References for CVE-2026-5524
Authoritative sources for CVE-2026-5524 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.