CVE-2026-6227

BackWPup <= 5.6.6 - Authenticated (Administrator+) Local File Inclusion via 'block_name' Parameter

highImproper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
7.2
CVSS Score
7.2
CVSS Score
high
Severity
5.6.7
Patched in
1d
Time to patch

Description

The BackWPup plugin for WordPress is vulnerable to Local File Inclusion via the `block_name` parameter of the `/wp-json/backwpup/v1/getblock` REST endpoint in all versions up to, and including, 5.6.6 due to a non-recursive `str_replace()` sanitization of path traversal sequences. This makes it possible for authenticated attackers, with Administrator-level access and above, to include arbitrary PHP files on the server via crafted traversal sequences (e.g., `....//`), which can be leveraged to read sensitive files such as `wp-config.php` or achieve remote code execution in certain configurations. Administrators have the ability to grant individual users permission to handle backups, which may then allow lower-level users to exploit this vulnerability.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=5.6.6
PublishedApril 13, 2026
Last updatedApril 14, 2026
Affected pluginbackwpup

What Changed in the Fix

Changes introduced in v5.6.7

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to exploit a Local File Inclusion (LFI) vulnerability in the BackWPup plugin for WordPress. ### 1. Vulnerability Summary The BackWPup plugin (<= 5.6.6) is vulnerable to Local File Inclusion via the `block_name` parameter in its REST API endpoint `/wp-json/backw…

Show full research plan

This research plan outlines the steps to exploit a Local File Inclusion (LFI) vulnerability in the BackWPup plugin for WordPress.

1. Vulnerability Summary

The BackWPup plugin (<= 5.6.6) is vulnerable to Local File Inclusion via the block_name parameter in its REST API endpoint /wp-json/backwpup/v1/getblock. The vulnerability exists because the plugin attempts to sanitize the block_name using a non-recursive str_replace() on the ../ sequence. By using a crafted sequence like ....//, an attacker can bypass the filter (the filter reduces ....// to ../). Since the endpoint includes the resulting path as a PHP file, an authenticated administrator (or user with backup permissions) can execute arbitrary PHP files or read files using PHP wrappers.

2. Attack Vector Analysis

  • Endpoint: /wp-json/backwpup/v1/getblock
  • Method: POST
  • Vulnerable Parameter: block_name
  • Required Authentication: Administrator (or users granted specific backup permissions).
  • Nonce Requirement: Required (X-WP-Nonce header). The nonce is tied to the wp_rest action for the REST API.
  • Preconditions: The plugin must be active. The attacker needs valid Administrator credentials.

3. Code Flow

  1. Entry Point: The REST route backwpup/v1/getblock is registered (likely in src/Infrastructure/Rest/Route/GetBlock.php, inferred from plugin structure).
  2. Handler: The callback function for this route retrieves the block_name and block_type parameters from the request.
  3. Sanitization: The code performs a check like $block_name = str_replace( '../', '', $block_name );.
  4. File Construction: The plugin constructs a file path: $file = BACKWPUP_PLUGIN_DIR . '/src/View/' . $block_type . '/' . $block_name . '.php'; (pathing inferred from backwpup-admin.js usage).
  5. Sink: The plugin uses include or require on the constructed path.

4. Nonce Acquisition Strategy

The REST API endpoint requires a standard WordPress REST nonce. This is exposed to the admin dashboard via the backwpupApi object.

  1. Access Dashboard: Navigate to the BackWPup "Jobs" or "Settings" page in the WordPress admin area.
  2. Locate Variable: The plugin localizes data into the backwpupApi JavaScript object.
  3. Extraction:
    • Use browser_navigate to http://localhost:8080/wp-admin/admin.php?page=backwpupjobs.
    • Use browser_eval to extract the nonce:
      window.backwpupApi?.nonce
      
  4. Endpoint Discovery: Also extract the base REST URL if needed: window.backwpupApi?.getblock.

5. Exploitation Strategy

We will attempt to include wp-config.php using a PHP filter wrapper to read its content in Base64 format, bypassing the limitation that include usually executes PHP rather than displaying source.

Step-by-Step Plan:

  1. Login: Authenticate as an administrator.
  2. Get Nonce: Extract the backwpupApi.nonce using the strategy above.
  3. Craft Payload:
    • The target file is wp-config.php, typically located 3 levels up from the plugin's view directory (wp-content/plugins/backwpup/src/View/...).
    • Using ....// to bypass str_replace('../', '', $input).
    • Payload: php://filter/convert.base64-encode/resource=....//....//....//....//wp-config (The .php extension is likely appended by the plugin).
  4. Execute Request:
    POST /wp-json/backwpup/v1/getblock
    Header: X-WP-Nonce: [EXTRACTED_NONCE]
    Header: Content-Type: application/x-www-form-urlencoded
    
    block_name=php://filter/convert.base64-encode/resource=....//....//....//....//wp-config&block_type=component
    
  5. Decode Output: The response body will contain the Base64 encoded content of wp-config.php.

6. Test Data Setup

  1. Plugin: Install and activate BackWPup version 5.6.6.
  2. User: Create an admin user (e.g., admin/password).
  3. Target File: Ensure wp-config.php exists in the standard location.

7. Expected Results

  • The REST API should return a 200 OK response.
  • The body should contain a Base64 string.
  • When decoded, the string should contain the PHP code of wp-config.php, including DB_NAME, DB_USER, and DB_PASSWORD.

8. Verification Steps

  1. HTTP Check: Verify the http_request response status and content.
  2. Base64 Decoding: Decode the result and verify the presence of the <?php tag and WordPress database constants.
  3. Comparison: Use wp-cli to check the actual wp-config.php content for verification:
    cat /var/www/html/wp-config.php
    

9. Alternative Approaches

  • Direct Traversal: If the PHP filter wrapper is blocked or fails, try direct traversal to a non-PHP file (if the plugin doesn't strictly append .php): ....//....//....//....//....//etc/passwd.
  • RCE via Upload: If the attacker can upload a file (e.g., via the "Backups" feature or media library), they can include that file using the LFI to gain Remote Code Execution.
  • Log Poisoning: If the server logs (like access.log) are reachable, poison the logs with PHP code and include the log file.
  • Block Type Manipulation: Try different block_type values if the directory structure differs (e.g., component, children, alerts). Based on backwpup-admin.js, component and children are valid block_type values.
Research Findings
Static analysis — not yet PoC-verified

Summary

The BackWPup plugin for WordPress is vulnerable to Local File Inclusion via the 'block_name' parameter in the '/wp-json/backwpup/v1/getblock' REST endpoint. This vulnerability stems from a non-recursive str_replace() filter that fails to properly sanitize path traversal sequences, allowing authenticated administrators (or users with backup permissions) to include arbitrary PHP files. Attackers can bypass the filter using crafted sequences like '....//' to read sensitive files such as 'wp-config.php' or achieve remote code execution.

Vulnerable Code

// src/Infrastructure/Rest/Route/GetBlock.php

public function handle( \WP_REST_Request $request ) {
    $block_name = $request->get_param( 'block_name' );
    $block_type = $request->get_param( 'block_type' );

    // Vulnerable: Non-recursive str_replace allows bypasses like ....//
    // Line number inferred
    $block_name = str_replace( '../', '', $block_name );

    $file = BACKWPUP_PLUGIN_DIR . '/src/View/' . $block_type . '/' . $block_name . '.php';

    if ( file_exists( $file ) ) {
        include $file;
    }
}

Security Fix

--- a/src/Infrastructure/Rest/Route/GetBlock.php
+++ b/src/Infrastructure/Rest/Route/GetBlock.php
@@ -15,1 +15,3 @@
-        $block_name = str_replace( '../', '', $block_name );
+        while ( strpos( $block_name, '../' ) !== false ) {
+            $block_name = str_replace( '../', '', $block_name );
+        }

Exploit Outline

To exploit this vulnerability, an attacker with Administrator-level access (or a user granted backup management permissions) must first obtain a valid REST API nonce. This nonce is typically exposed in the admin dashboard within the 'backwpupApi' JavaScript object. The attacker then sends a POST request to the '/wp-json/backwpup/v1/getblock' endpoint with the 'block_name' parameter set to a crafted path traversal payload. By using a sequence like '....//', the attacker bypasses the plugin's non-recursive 'str_replace' filter, which reduces the sequence to '../'. This allows the attacker to traverse directories and include arbitrary PHP files. For example, using a PHP filter wrapper like 'php://filter/convert.base64-encode/resource=....//....//....//....//wp-config' allows the attacker to read the contents of 'wp-config.php' in Base64 format.

Check if your site is affected.

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