CVE(s):

CVE-2025-67082

CVE-2025-67083

CVE-2025-67084

Product:

InvoicePlane

Severity:

High

Affected version(s):

≤ 1.6.3

Fixed version(s):

1.6.4

Introduction

InvoicePlane is a self-hosted, open-source web application designed to manage quotes, invoices, clients, and payments. It is used by small businesses and freelancers as an invoicing and billing solution.

Issue

Multiple security vulnerabilities were identified in InvoicePlane that affect the version "1.6.3". These issues include unauthenticated file read, authenticated SQL injection, and authenticated arbitrary PHP file upload, which may lead to remote code execution (RCE).

At the time of discovery, InvoicePlane does not implement role separation: the only available user role is an administrator role. While this limits privilege escalation scenarios, the impact of authenticated vulnerabilities remains significant due to the high level of access granted by default.

Timeline

Date Description
18/08/2025 Reporting vulnerabilities through the GitHub project
21/08/2025 Response from the publisher and start of corrections
01/12/2025 v1.6.4-beta-1 fixes vulnerabilities
06/01/2026 CVE identifiers have been reserved

Technical details

Unauthenticated File Read / CVE-2025-67083

An unauthenticated attacker can read files from the server through a directory traversal vulnerability. The extent of file access depends on the web server configuration and filesystem permissions.

The vulnerable endpoint is: /guest/get/get_file/<filename>


public function get_file($filename): void
    {
        $filename = urldecode($filename);
        if ( ! file_exists($this->targetPath . $filename)) {
            $ref = isset($_SERVER['HTTP_REFERER']) ? ', Referer:' . $_SERVER['HTTP_REFERER'] : '';
            $this->respond_message(404, 'upload_error_file_not_found', $this->targetPath . $filename . $ref);
        }

        $path_parts = pathinfo($this->targetPath . $filename);
        $file_ext   = mb_strtolower($path_parts['extension'] ?? '');
        $ctype      = $this->content_types[$file_ext] ?? $this->ctype_default;

        $file_size = filesize($this->targetPath . $filename);

        header('Expires: -1');
        header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
        header('Pragma: no-cache');
        header('Content-Disposition: attachment; filename="' . $filename . '"');
        header('Content-Type: ' . $ctype);
        header('Content-Length: ' . $file_size);

        readfile($this->targetPath . $filename);
    }

The filename parameter is used without proper sanitization or validation, allowing traversal sequences (e.g. ../) to be injected. This enables an attacker to access arbitrary files on the server, subject to web server restrictions.

This vulnerability may allow attackers to read sensitive configuration files, logs, or other application data.

Authenticaded SQL injection / CVE-2025-67082

An authenticated user can inject arbitrary SQL commands via vulnerable POST parameters in the reporting functionality.

The issue occurs in the file Mdl_reports.php, where the minQuantity and maxQuantity parameters are directly embedded into an SQL query without proper sanitization or the use of prepared statements.


$this->db->where('
  (
  SELECT SUM(amounts.invoice_total) FROM ip_invoice_amounts amounts
      WHERE amounts.invoice_id IN
      (
          SELECT inv.invoice_id FROM ip_invoices inv
              WHERE inv.client_id=ip_clients.client_id
                  AND ' . $this->db->escape($from_date) . ' <= inv.invoice_date_created
                  AND ' . $this->db->escape($to_date) . ' >= inv.invoice_date_created
                  AND ' . $minQuantity . ' <=
                  (
                      SELECT SUM(amounts2.invoice_total) FROM ip_invoice_amounts amounts2
                          WHERE amounts2.invoice_id IN
                          (
                              SELECT inv2.invoice_id FROM ip_invoices inv2
                                  WHERE inv2.client_id=ip_clients.client_id
                                      AND ' . $this->db->escape($from_date) . ' <= inv2.invoice_date_created
                                      AND ' . $this->db->escape($to_date) . ' >= inv2.invoice_date_created
                          )
                  )
      )
) <>0');

Because these parameters are not safely handled, an attacker can manipulate the SQL query, potentially leading to:

  • Disclosure of sensitive database information
  • Modification or deletion of data
  • Abuse of database functionality depending on permissions

Authenticated Arbitrary PHP File Upload / CVE-2025-67084

An authenticated user can upload arbitrary PHP files through the attachment upload functionality, ultimately leading to remote code execution.

In the upload handler Upload.php, a MIME type check is partially implemented:


$tempFile = $_FILES['file']['tmp_name'];
if (extension_loaded('fileinfo')) {
    $this->validate_mime_type(mime_content_type($tempFile));
}

However, the function is based on an array containing the authorised content types, including text/plain. It is then possible to upload a PHP file while declaring a benign MIME type such as text/plain.

Once uploaded, these PHP files can be accessed and executed by the server, allowing an attacker to execute arbitrary code in the context of the web application.

Resources