Image Optimizer <= 1.7.4 - Authenticated (Author+) Arbitrary File Deletion via Post Meta Field Injection
Description
The Image Optimizer plugin for WordPress is vulnerable to arbitrary file deletion in versions up to and including 1.7.4. This is due to insufficient path validation in the Image_Backup::remove() function where backup file paths stored in post meta are used directly in file deletion operations without verifying they are within the uploads directory. The plugin stores backup file paths in the image_optimizer_metadata post meta field and trusts these paths completely when deleting backups on the delete_attachment hook. An authenticated attacker with Author-level access can edit the image_optimizer_metadata post meta on their own attachments via WordPress's Custom Fields interface, injecting arbitrary absolute file paths into the backups array. When the attacker subsequently deletes the attachment, the plugin calls File_System::delete() on each path without validation. This makes it possible for authenticated attackers, with Author-level access and above, to delete arbitrary files on the server within the web server's filesystem permissions, potentially leading to denial of service, data loss, or security degradation.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:HTechnical Details
<=1.7.4What Changed in the Fix
Changes introduced in v1.7.5
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-5821 ## 1. Vulnerability Summary The **Image Optimization – Compress Images and Convert to WebP or AVIF** plugin (versions <= 1.7.4) is vulnerable to authenticated arbitrary file deletion. The vulnerability exists in the `Image_Backup::remove()` function, whi…
Show full research plan
Exploitation Research Plan - CVE-2026-5821
1. Vulnerability Summary
The Image Optimization – Compress Images and Convert to WebP or AVIF plugin (versions <= 1.7.4) is vulnerable to authenticated arbitrary file deletion. The vulnerability exists in the Image_Backup::remove() function, which is hooked into WordPress's delete_attachment action.
The plugin stores paths to backup files in the image_optimizer_metadata post meta field (specifically within a backups array). When an attachment is deleted, the plugin retrieves this meta, iterates through the backups array, and calls File_System::delete() on each path. Because the plugin fails to validate that these paths are restricted to the expected uploads directory, an attacker with Author-level permissions can modify the post meta of an attachment they own to include arbitrary absolute file paths. Deleting the attachment then triggers the deletion of those files.
2. Attack Vector Analysis
- Endpoint:
wp-admin/post.php(for both meta update and attachment deletion). - Vulnerable Hook:
delete_attachment. - Vulnerable Sink:
File_System::delete($path). - Payload Parameter: The
metavaluefor theimage_optimizer_metadatakey. - Preconditions:
- Attacker must have at least Author level access (to upload and manage their own attachments).
- The target file must be writable/deletable by the web server user (e.g.,
www-data).
- Required Knowledge: The absolute path of the target file on the server.
3. Code Flow
- Entry Point: A user with
delete_postscapability (Author+) deletes an attachment. - Hook Trigger: WordPress fires the
delete_attachmenthook. - Plugin Execution: The plugin's registered callback
Image_Backup::remove($post_id)(inferred) is executed. - Data Retrieval: The function calls
get_post_meta($post_id, 'image_optimizer_metadata', true). - Payload Processing: The code accesses the
backupskey from the returned meta array/object:// Inferred logic based on description $meta = get_post_meta($post_id, 'image_optimizer_metadata', true); if (isset($meta['backups']) && is_array($meta['backups'])) { foreach ($meta['backups'] as $backup_path) { File_System::delete($backup_path); // SINK } } - Sink Execution:
File_System::delete()executesunlink()or a similar filesystem operation on the unvalidated$backup_path.
4. Nonce Acquisition Strategy
Since the attacker is an Author, they have access to the WordPress Admin dashboard. Nonces are required for updating post meta and deleting the post.
- Meta Update Nonce: Found in the attachment edit page (
wp-admin/post.php?post=[ID]&action=edit). The nonce for adding/updating custom fields is typically named_wpnoncein the main edit form or specificallyaddmetafor the custom fields AJAX. - Deletion Nonce: Found in the attachment edit page or the Media Library. The action is
delete-post-[ID], and the nonce is usually passed as_wpnoncein the deletion URL:post.php?action=delete&post=[ID]&_wpnonce=[NONCE].
Strategy:
- Use
browser_navigateto go to the attachment edit page. - Use
browser_evalto extract the_wpnoncefrom the form. - Use
browser_evalto extract the_wpnoncefrom the "Delete Permanently" link.
5. Exploitation Strategy
The goal is to delete a sensitive file (e.g., wp-config.php or a test file).
- Step 1: Setup
- Create an Author user.
- Create a dummy file at
/tmp/pwned.txtto safely demonstrate deletion.
- Step 2: Login and Upload
- Login as the Author.
- Upload a legitimate image to get an attachment ID (
$ATTACH_ID).
- Step 3: Inject Payload into Post Meta
- Navigate to the edit page for
$ATTACH_ID. - Use the Custom Fields interface to add or update the
image_optimizer_metadatakey. - Payload (Serialized PHP):
a:1:{s:7:"backups";a:1:{i:0;s:14:"/tmp/pwned.txt";}} - Note: WordPress
get_post_metawith$single=truewill automaticallymaybe_unserializethis string into the array the plugin expects.
- Navigate to the edit page for
- Step 4: Trigger Deletion
- Submit a request to
post.php?action=delete&post=$ATTACH_ID&_wpnonce=$DEL_NONCE.
- Submit a request to
- Step 5: Verify
- Check if
/tmp/pwned.txtstill exists.
- Check if
6. Test Data Setup
- Target File:
/tmp/pwned.txt(ensure web server has permission to delete). - User: Username:
attacker, Password:password123, Role:author. - Media: A standard image file (e.g.,
test.png) uploaded byattacker.
7. Expected Results
- The request to
action=deletereturns a 302 redirect to the Media Library. - The attachment is removed from the database (
wp_poststable). - The file
/tmp/pwned.txtis successfully deleted from the filesystem.
8. Verification Steps
- Via WP-CLI:
# Check if attachment is gone wp post exists [ID] # Check if file is gone ls /tmp/pwned.txt - Check Database:
wp db query "SELECT * FROM wp_postmeta WHERE post_id = [ID] AND meta_key = 'image_optimizer_metadata'"
9. Alternative Approaches
If the Custom Fields UI is disabled or hidden:
- REST API: Check if the Author can update meta via
POST /wp-json/wp/v2/media/[ID]. This requires theimage_optimizer_metadatato be registered withshow_in_rest => true. - Direct AJAX: Attempt to use the
add-metaaction inadmin-ajax.phpwhich is the backend for the Custom Fields UI:POST /wp-admin/admin-ajax.php Content-Type: application/x-www-form-urlencoded action=add-meta&_ajax_nonce-add-meta=[NONCE]&post_id=[ID]&metakeyinput=image_optimizer_metadata&metavalue=[SERIALIZED_PAYLOAD]
Summary
The Image Optimizer plugin for WordPress is vulnerable to arbitrary file deletion because it fails to validate file paths retrieved from post meta before using them in a deletion operation. Authenticated attackers with Author-level permissions can modify an attachment's metadata to include absolute server paths, which the plugin subsequently deletes when the attachment is removed.
Vulnerable Code
// Inferred from vulnerability description // Path: includes/image-backup.php public function remove( $post_id ) { $meta = get_post_meta( $post_id, 'image_optimizer_metadata', true ); if ( ! empty( $meta['backups'] ) && is_array( $meta['backups'] ) ) { foreach ( $meta['backups'] as $file_path ) { // Vulnerable: $file_path is taken directly from post meta without path validation File_System::delete( $file_path ); } } }
Security Fix
@@ -4,7 +4,11 @@ $meta = get_post_meta( $post_id, 'image_optimizer_metadata', true ); if ( ! empty( $meta['backups'] ) && is_array( $meta['backups'] ) ) { + $upload_dir = wp_upload_dir(); foreach ( $meta['backups'] as $file_path ) { - File_System::delete( $file_path ); + // Validate that the file path is located within the WordPress uploads directory + if ( strpos( wp_normalize_path( $file_path ), wp_normalize_path( $upload_dir['basedir'] ) ) === 0 ) { + File_System::delete( $file_path ); + } } }
Exploit Outline
1. Authenticate as an Author or higher and upload an image to the media library to generate a target attachment ID. 2. Access the attachment's edit page in the WordPress admin dashboard to view the Custom Fields interface. 3. Modify or add the 'image_optimizer_metadata' meta key, injecting a serialized PHP array containing a 'backups' list that includes the absolute system path of the target file to be deleted (e.g., '/var/www/html/wp-config.php'). 4. Send a request to 'wp-admin/post.php?action=delete' for the attachment ID, including the necessary security nonces obtained from the admin UI. 5. The plugin's hook for the 'delete_attachment' action will trigger, causing the 'Image_Backup::remove' function to process the malicious meta and delete the targeted file.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.