CVE-2024-53353: SSRF Vulnerability in Invoice Ninja
Impact
The CVE-2024-53353 allows Invoice Ninja local users with the 'read' and 'create' invoice permissions to enter malicious payloads in order to read local files through Server-Side Request Forgery (SSRF) on PDF generation. The same attack vector can be triggered by clients that have access to the client portal, so they can modify their personal data to trigger the attack when a quote gets generated for them.
In both cases, the impact is the same: an attacker could read system files from the underlying host, which could end up compromising cleartext credentials and other useful sensitive data.
Static Code Analysis
To gain deeper insights into the PDF generation process within Invoice Ninja, we performed a static code analysis of the codebase available on GitHub. Using the default “snappdf” package to generate PDFs in the application, we observed that HTML tags such as “<u>test</u>
” were being properly rendered but tags such as “<iframe>
” or “<script>
” were being removed. This led us to explore the underlying code for PDF generation in greater detail.
The following file, located on “app/Utils/Traits/Pdf/PdfMaker.php
”, was responsible for this task and had the interesting filter below:
Here’s a breakdown of how the filter works:
str_replace()
: A PHP function that replaces all occurrences of the search strings in the subject string with the corresponding replacement strings. In this case, it's replacing certain strings in the HTML content represented by the variable$html
.['file:/', 'iframe', '<object', '<object', '127.0.0.1', 'localhost']
: This array lists the elements the code is designed to identify and replace['', '', '', '', '', '']
: This array specifies the values to replace the search strings with. Since all the replacement strings are empty (''), it effectively removes the matched strings from the HTML content.
So, let's see what each of these search strings represents:
'file:/'
: This is an attempt to remove occurrences of "file:/" from the HTML. This may be an attempt to prevent access to local files via the "file://" protocol, which could be used for various security attacks.'iframe'
: This string indicates an attempt to remove occurrences of the<iframe>
tag from the HTML. Iframes can be used for various purposes, including embedding external content, but they can also be exploited for malicious purposes such as clickjacking and cross-site scripting (XSS) attacks.'<object'
and'<object'
: These strings represent attempts to remove occurrences of the <object> tag from the HTML. Like iframes, object tags can be used for embedding various types of content, including multimedia and interactive elements. Removing them might be an attempt to prevent certain types of attacks, such as plugin-based vulnerabilities.'127.0.0.1'
and'localhost'
: These strings represent attempts to remove occurrences of references to localhost (e.g., in URLs). This could be an attempt to prevent certain types of attacks that involve local network communication or accessing resources on the local machine.
Blacklist filtering is a reactive approach to security, relying solely on identifying and blocking known patterns of malicious content. While it might provide a basic level of defense, it has significant limitations that leave systems vulnerable to more sophisticated attacks.
Attackers can easily bypass such filters by using alternative representations of the same malicious content or by using entirely different attack vectors that are not included in the blacklist. For instance instead of using “file://
” an attacker could use “File://
” which would still work. Or, instead of “<iframe>
” an attacker could use “<IFRAME>
” since in PHP, the str_replace()
function, as used in the provided code snippet, is case-sensitive meaning only exact matches are filtered out.
Exploiting the Vulnerability
This vulnerability can be exploited through two distinct methods: one involves using the main portal with either an administrator role or a user with permissions to view and edit invoices, while the other leverages the client portal.
Scenario 1: Exploiting the Main Portal
In this scenario, the vulnerability is exploited through the main portal by a user with the “Edit” or “Create” invoice role assigned. While we demonstrate the issue using the “Invoices” tab, it's important to note that the vulnerability is present across any function that offers PDF generation and includes a “Description” field. This includes features like “Quotes,” “Recurring Invoices,” “Tasks,” and more.
- Log into the application using a user which has the “Create/Edit Invoice” permissions.
- From the left menu, navigate to the “Invoices” tab then click on “New Invoice” as highlighted in the figure below:
- In the “Client” field, choose an existing client or create a new one.
- Under the “Products/Tasks” section, click on “Add Item”.
- Then in the “Description” field, enter the following payload:
<embed src=”File:///etc/passwd”>
- If the “PDF Live Preview” option is enabled, then click anywhere outside the description field to generate and render the PDF, otherwise download the PDF manually.
- As seen in the figure below, the contents of the “
/etc/passwd
” file were loaded successfully in the PDF since we were able to access the file using “File://
” protocol.
- Since InvoiceNinja uses the "
.env
” file for environmental variables and configuration, an attacker knowing the full path of the application can use the following payload to read the content of the “.env
” file:<embed src="/usr/share/nginx/invoiceninja/.env" width="900" height="900">
As seen in the figures above, an attacker can abuse this vulnerability to read internal files which can contain hardcoded credentials such as in the case of the “.env
” file. In this file there are multiple configurations such as the database credentials, SMTP credentials, or credentials for third party services.
Scenario 2: Exploiting the Client Portal
This scenario involves exploiting the vulnerability through the client portal using a low-privileged user account. The user can self-register on the client portal, making it easier to gain access without administrative oversight. While the security impact is more severe than in the main portal scenario, exploiting this vulnerability requires a “Quote” to be sent to the client, triggering the PDF generation process.
- If the client portal is disabled for your instance, you can enable it by navigating to “Settings” then “Client Portal”.
- Toggle the “Client Portal” button to enable it.
- Then navigate to the “Registration” tab and enable “Client Registration”
- Register for an account by navigating to “https://your_instance/client”
- After logging in as a client, we will observe that there’s no data on “Quotes” or other menus.
- From the main portal, initiate a “Quote” to the newly created client, using an account which has the necessary permissions.
- Return to the “Quotes” tab in the main portal, click the “More Actions” button, and select either “Email Quote” or “Mark as Sent” to ensure the quote becomes visible on the client portal..
- Using the client user navigate to “Quotes” and observe that the “Quote” has appeared.
- Before clicking on “View”, navigate to the client profile settings from the top right menu.
- Modify the “Name” field or any other field that appears on the generated PDF, input the following payload, and save your changes:
<embed src=”File:///etc/passwd”>
- Save your profile settings, then navigate to “Quotes” and click on “View”.
As seen in the previous figure, the content of the “/etc/passwd” file was rendered on the generated PDF.
In conclusion, an attacker with low privileges simply requires a quote to be sent to their account. From there, they can modify their profile settings and inject various payloads to access internal system files.
Remediation
To address this vulnerability, it is recommended to update Invoice Ninja to its latest version.
Conclusion
The SSRF vulnerability in Invoice Ninja’s PDF generation highlights the importance of proactive security practices. Blacklist filtering, while simple, is often insufficient against sophisticated attacks. Adopting whitelist-based input validation and leveraging secure coding standards can significantly reduce the risk of exploitation. By addressing these vulnerabilities, organizations can ensure the integrity and security of their systems in an increasingly connected world.
Timeline of Responsible Disclosure
- July 5: Initial email sent to Invoice Ninja, detailing the vulnerability in the SnapPDF library and offering assistance.
- July 17: Follow-up email sent to inquire about the status of the reported issue.
- November 19: Follow-up LinkedIn message sent to inquire about the status of the reported issue.
- End of November: Our team members learned that this vulnerability has been silently fixed by the Invoice Ninja team on July 6, 2024, as stated in this GitHub commit.
- December 3: CVE-2024-53353 was approved by MITRE, documenting the vulnerability to raise awareness and support remediation efforts.
- December 26: Release of the current responsible disclosure.
Appendix: Installation and Configuration
When setting up Invoice Ninja, we followed the installation steps recommended by the community on the Invoice Ninja Forum.
For reference, here are the key resources we utilized:
- https://invoiceninja.github.io/en/self-host-installation/
- https://forum.invoiceninja.com/t/install-invoice-ninja-v5-on-ubuntu-20-04/4588
One critical configuration step involved editing the .env
file. Specifically, we set the PDF generator to use snappdf
. This was done by adding the following line to the .env
file: PDF_GENERATOR=snappdf
After completing the installation and configuring the .env
file, we proceeded to set up Invoice Ninja on a Linux server. The final step in our setup process was pointing the application to our domain: invoiceninja.pretera.com