Prevention of CSV injection attacks
using System;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Mvc;
namespace VulnerableApp.Controllers
{
public class ExportController : Controller
{
[HttpGet]
public IActionResult ExportData()
{
var csv = new StringBuilder();
// Assume we get data from database.
var data = new[]
{
new {Id = 1, Name = "John", Email = "john@example.com"},
new {Id = 2, Name = "Jane", Email = "jane@example.com"}
};
foreach (var item in data)
{
var newLine = $"{item.Id},{item.Name},{item.Email}";
csv.AppendLine(newLine);
}
return File(new MemoryStream(Encoding.UTF8.GetBytes(csv.ToString())), "text/csv", "Data.csv");
}
}
}
The above code is a simple implementation of a method in a controller that exports data to a CSV file in an ASP.NET Core application. The data is assumed to be retrieved from a database, and then it is written to a CSV string line by line. Each line contains the id, name, and email of a user, separated by commas.
The vulnerability lies in the fact that the data is directly written to the CSV without any checks or sanitization. This allows for CSV Injection attacks.
An attacker could inject a malicious formula as part of the user data (for instance, in the
Name
or
Email
field). When this data is exported and the CSV file is opened in a spreadsheet program like Excel, the formula will be executed. This can lead to various security issues, such as data exfiltration, remote code execution, etc.
For instance, if an attacker enters
=1+1
as their name, when the CSV is opened in Excel, the cell will display
2
instead of
=1+1
. This is a simple example, but the formula could be much more dangerous, like
=CMD|' /C calc'!A0
which can lead to remote code execution.
using System;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Mvc;
namespace VulnerableApp.Controllers
{
public class ExportController : Controller
{
[HttpGet]
public IActionResult ExportData()
{
var csv = new StringBuilder();
// Assume we get data from database.
var data = new[]
{
new {Id = 1, Name = "John", Email = "john@example.com"},
new {Id = 2, Name = "Jane", Email = "jane@example.com"}
};
foreach (var item in data)
{
var newLine = $"{item.Id},{Sanitize(item.Name)},{Sanitize(item.Email)}";
csv.AppendLine(newLine);
}
return File(new MemoryStream(Encoding.UTF8.GetBytes(csv.ToString())), "text/csv", "Data.csv");
}
private string Sanitize(string input)
{
if (input.StartsWith("=") || input.StartsWith("+") || input.StartsWith("-") || input.StartsWith("@"))
{
return "'" + input;
}
return input;
}
}
}
The above code fixes the CSV Injection vulnerability by sanitizing the data before adding it to the CSV file. The
Sanitize
method checks if the input string starts with any of the characters that can be used to inject formulas into CSV files (
=
,
+
,
-
,
@
). If it does, it prepends a single quote (
'
) to the input string. This single quote will be interpreted by Excel as an indicator that the following content should be treated as a string, preventing any formulas from being executed.
This solution also adheres to the principle of using built-in functionality to generate the CSV file instead of manually constructing it. The
StringBuilder
class is used to construct the CSV file, ensuring that it is properly formatted and does not allow the injection of formulas.
Furthermore, this solution validates and restricts the input data to prevent any malicious content from being included in the CSV file. The
Sanitize
method ensures that only safe data is included in the CSV file.
Finally, it is important to educate developers about the risks of CSV injection and provide guidelines on secure coding practices. This solution serves as an example of how to securely generate CSV files in ASP.NET Core.