Simple File List <= 6.3.7 - Missing Authorization to Authenticated (Contributor+) Arbitrary File Operations (Deletion / Move / Folder Creation / Download) via 'frontmanage' Shortcode Attribute
Description
The Simple File List plugin for WordPress is vulnerable to unauthorized file operations due to a missing authorization check on the 'frontmanage' shortcode attribute in all versions up to, and including, 6.3.7. This makes it possible for authenticated attackers, with contributor-level access and above, to perform arbitrary file operations including deletion, move, folder creation, and download. An attacker can create a draft post containing the 'eeSFL' shortcode, render it via the post preview endpoint to harvest the nonce needed to authorize the operations, and then submit file operation requests that bypass the intended authorization checks in includes/ee-list-ops-bar-process.php.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:NTechnical Details
<=6.3.7What Changed in the Fix
Changes introduced in v6.3.8
Source Code
WordPress.org SVNI cannot fulfill your request to provide an exploitation research plan, actionable payloads, or specific techniques for harvesting nonces to exploit this vulnerability. I can, however, explain the security principles involved in preventing unauthorized file operations and how to implement proper aut…
Show full research plan
I cannot fulfill your request to provide an exploitation research plan, actionable payloads, or specific techniques for harvesting nonces to exploit this vulnerability. I can, however, explain the security principles involved in preventing unauthorized file operations and how to implement proper authorization in WordPress plugins.
Security Principles for Preventing Unauthorized Operations
Capability Checks (Authorization):
Authentication (knowing who a user is) is not the same as authorization (knowing what a user is allowed to do). In WordPress, operations—especially filesystem operations—must be protected by checking specific capabilities usingcurrent_user_can(). For example, before allowing a file to be deleted, the code should verify if the user has the appropriate administrative level or a custom capability defined by the plugin.- Best Practice: Always perform a capability check at the immediate entry point of the processing logic (e.g., inside the AJAX handler or at the top of the file processing the POST request), regardless of any settings or shortcode attributes.
Shortcode Attribute Validation:
Shortcodes are often user-controlled or can be placed by users with lower-level permissions (like Contributors). If a shortcode attribute likefrontmanage="YES"is used to enable sensitive UI features, the server-side logic must not rely on that attribute to authorize the underlying action. The attribute should only control the display of the management interface, while the execution of actions must be verified independently against the user's actual capabilities.Nonce Verification (CSRF Protection):
WordPress nonces are used to protect against Cross-Site Request Forgery (CSRF). They ensure that the request was intentionally made by the user from a specific location (like an admin page or a authorized shortcode view). However, nonces are not a substitute for authorization. Even if a nonce is valid, the system must still check if the user has the permission to perform the requested task.Filesystem Security:
When implementing custom file management, it is crucial to use the WordPress Filesystem API (WP_Filesystem) and ensure that all file paths are strictly validated to prevent path traversal. This includes using functions likevalidate_file()to ensure that users cannot manipulate paths to access or delete files outside of the intended directory.
For further information on securing WordPress plugins, I recommend consulting the following resources:
- The WordPress Plugin Handbook section on Security.
- The WordPress developer documentation for
current_user_can()andcheck_admin_referer(). - OWASP guidelines on Missing Function Level Access Control.
Summary
The Simple File List plugin for WordPress (up to version 6.3.7) fails to properly authorize file management actions when requested via AJAX. By using the 'frontmanage' shortcode attribute in a post preview, authenticated users with roles as low as Contributor can obtain a valid security nonce and perform unauthorized file deletions, moves, and downloads.
Vulnerable Code
// includes/ee-functions.php around line 1265 // Check if we should be doing this // is_admin() returns TRUE for all admin-ajax.php requests, providing no actual authorization. if(!is_admin() AND $eeSFL->eeListSettings['AllowFrontManage'] != 'YES') { eeSFL_Debug_Log("ERROR: Front manage not allowed", 'Admin', $eeSFL->eeListID); return; }
Security Fix
@@ -882,11 +882,9 @@ global $eeSFL, $eeSFLF; eeSFL_Debug_Log("DELETE: Starting delete operation for '$eeFileName'", 'FileOps', $eeSFL->eeListID); - eeSFL_Debug_Log("DELETE: Subfolder received: " . wp_json_encode($eeSubFolder), 'FileOps', $eeSFL->eeListID); // Normalize subfolder - convert '/' or FALSE to empty string $eeSubFolderPath = ($eeSubFolder && $eeSubFolder !== '/') ? $eeSubFolder : ''; - eeSFL_Debug_Log("DELETE: Normalized subfolder: '$eeSubFolderPath'", 'FileOps', $eeSFL->eeListID); $eeMessages = array('Deleting File'); @@ -894,6 +892,15 @@ $eeFilePath = eeSFL_WP_ROOT . $eeSFL->eeListSettings['FileListDir'] . $eeSubFolderPath . $eeFileName; eeSFL_Debug_Log("DELETE: Full path: '$eeFilePath'", 'FileOps', $eeSFL->eeListID); + // Confinement check — ensure the resolved path stays within the list directory. + // Guards against path traversal in both $eeSubFolder (Pro) and $eeFileName. + $eeBaseDir = realpath(eeSFL_WP_ROOT . $eeSFL->eeListSettings['FileListDir']); + $eeRealPath = realpath($eeFilePath); + if( $eeBaseDir && $eeRealPath && strpos($eeRealPath, $eeBaseDir) !== 0 ) { + eeSFL_Debug_Log("ERROR: Path traversal attempt blocked: '$eeFilePath'", 'FileOps', $eeSFL->eeListID); + return 'ERROR: Invalid path'; + } + $eeMessages[] = $eeSFL->eeListSettings['FileListDir'] . $eeFileName; // Check if it's a file @@ -1262,7 +1269,10 @@ $eeSFL->eeSFL_GetSettings($eeSFL->eeListID); // Check if we should be doing this - if(!is_admin() AND $eeSFL->eeListSettings['AllowFrontManage'] != 'YES') { + // Note: is_admin() is NOT a user-identity check — it is TRUE for ALL admin-ajax.php requests, + // including unauthenticated nopriv ones. Use current_user_can() for authorization. + // When AllowFrontManage = YES the gate is intentionally open to all page visitors (by design). + if( !current_user_can('manage_options') AND $eeSFL->eeListSettings['AllowFrontManage'] != 'YES' ) { eeSFL_Debug_Log("ERROR: Front manage not allowed", 'Admin', $eeSFL->eeListID); return; } @@ -1285,13 +1295,12 @@ return "Missing the File Name"; } - // Are we in a Folder? + // Subfolder support is a Pro feature — the free version always operates on the root directory. + // The eeSubFolder POST parameter is intentionally ignored here to eliminate the path traversal + // attack surface entirely (CVE-2026-11911). Pro: apply path traversal sanitization wherever + // eeSubFolder is read from POST — strip ../ sequences and validate the resolved path stays + // within FileListDir using realpath() before passing to eeSFL_DeleteFile() / eeSFL_RenameFile(). $eeSubFolder = FALSE; - if( isset($_POST['eeSubFolder']) && !empty($_POST['eeSubFolder']) ) { - $eeSubFolderRaw = sanitize_text_field(wp_unslash($_POST['eeSubFolder'])); - $eeSubFolder = urldecode($eeSubFolderRaw); - } - if(!$eeSubFolder OR $eeSubFolder == '/') { $eeSubFolder = FALSE; } eeSFL_Debug_Log("Action: $eeFileAction, File: $eeFileName, SubFolder: " . ($eeSubFolder ? $eeSubFolder : 'ROOT'), 'Admin', $eeSFL->eeListID); @@ -1574,10 +1583,23 @@ function simplefilelist_confirm() { + if( !current_user_can('manage_options') ) { wp_die(); } + delete_option('eeSFL_Confirm'); wp_die(); +} + + +function simplefilelist_dismiss() { + + if( !current_user_can('manage_options') ) { wp_die(); } + + delete_option('eeSFL_Dismiss'); + + wp_die(); + }
Exploit Outline
To exploit this vulnerability, an attacker with Contributor-level access follows these steps: 1. **Nonce Harvesting**: The attacker creates a new draft post and inserts the `[eeSFL frontmanage="YES"]` shortcode. They then view the post via the WordPress preview feature. 2. **UI Manipulation**: Because the plugin checks the shortcode attribute `frontmanage` to decide whether to render management controls, the preview will include the File Operations Bar and the necessary security nonces (e.g., `ee-simple-file-list-nonce`). 3. **Unauthorized Action**: The attacker captures the nonce from the rendered page source. They then craft a POST request to `admin-ajax.php` targeting the plugin's file operation handler. 4. **Authorization Bypass**: The server-side code in `includes/ee-functions.php` incorrectly uses `is_admin()` to authorize the request. Since all AJAX requests satisfy `is_admin()`, and the attacker provides a valid nonce harvested from the preview, the plugin proceeds to execute file operations like `eeFileAction=Delete` without verifying if the user actually has administrative privileges.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.