# Arbitrary File Writes

If your web-server writes files to disk, the output filename and path should not be generated from untrusted input. A web-server that permits **arbitrary file writes** to be triggered by specially crafted HTTP requests will allow an attacker to drop malicious files on your server or overwrite existing resources.

## Arbitrary File Writes in C#

File upload functions on websites are a favorite target for hackers because they can write a potentially malicious file to your server. If the filename is taken from the HTTP request, the attacker can control where in the directory the file is written to. If the attacker can include *relative path* syntax in the filename, they can write to *any* location on the server.
The following C# snippet shows a profile photo upload function that takes the filename from a multipart form request in an ASP.NET Core web application:

“`csharp
[HttpPost]
[Route(“profile/image”)]
public async Task<IActionResult> UploadProfilePhoto()
{
var request = HttpContext.Request;if (!request.HasFormContentType ||
!MediaTypeHeaderValue.TryParse(request.ContentType, out var mediaTypeHeader) ||
string.IsNullOrEmpty(mediaTypeHeader.Boundary.Value))
{
return new UnsupportedMediaTypeResult();
}
var reader = new MultipartReader(mediaTypeHeader.Boundary.Value, request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition,
out var contentDisposition);
if (hasContentDispositionHeader && contentDisposition.DispositionType.Equals(“form-data”) &&
!string.IsNullOrEmpty(contentDisposition.FileName.Value))
{
// The construction of the the path is not safe – if it
// contains the “..%2F” pattern, it will be treated as
// ../ and a hacker can climb out of the static directory.
var saveToPath = Path.Combine(“Profiles”, contentDisposition.FileName.Value);
using (var targetStream = System.IO.File.Create(saveToPath))
{
await section.Body.CopyToAsync(targetStream);
}
return Ok();
}
section = await reader.ReadNextSectionAsync();
}
return BadRequest(“No file data in the request.”);
}
“`

This function takes the filename from the HTTP request. In a normal interaction with the browser, this is the name of the file the user has selected to upload. However, with a few lines of code, an attacker can craft a script to upload a file with an arbitrary filename like `../command.sh` The `../` syntax in the “filename” will be interpreted as a request to move to the parent directory by the `Path.Combine(…)` method. This allows the attacker to “climb out” of the intended output directory. Using this syntax multiple times allows them to write their malicious file *anywhere* on the server’s file system.

## Mitigation

One easy way to mitigate this attack is to remove suspicious characters from the filename. Here we simply replace any character that is not alphanumeric (or a period) with an underscore character:

“`csharp
if (hasContentDispositionHeader && contentDisposition.DispositionType.Equals(“form-data”) &&
!string.IsNullOrEmpty(contentDisposition.FileName.Value))
{
// Replacing non-alphanumeric characters with an underscore
// will stop an attacker traversing directories.
var safeFileName = Regex.Replace(contentDisposition.FileName.Value, “[^0-9a-zA-Z\.]+”, “_”);
var saveToPath = Path.Combine(“Profiles”, safeFileName);using (var targetStream = System.IO.File.Create(saveToPath))
{
await section.Body.CopyToAsync(targetStream);
}
return Ok();
}
“`

This still allows the attacker to write the file with any extension they please, and potentially overwrite any files that exist with that name. The best approach is to generate a name for the file on the server – either a completely random name, or something meaningful, like `<username>-profile.jpg`. You will have to record this filename to a database (e.g. against the record for that user) to make use of it later:

“`csharp
if (hasContentDispositionHeader && contentDisposition.DispositionType.Equals(“form-data”) &&
!string.IsNullOrEmpty(contentDisposition.FileName.Value))
{
// Choosing our own filename secures the upload function.
var safeFileName = Path.GetRandomFileName() + “-profile.jpg”;
var saveToPath = Path.Combine(“Profiles”, safeFileName);using (var targetStream = System.IO.File.Create(saveToPath))
{
await section.Body.CopyToAsync(targetStream);
}
return Ok();
}
“`

## Further Considerations

* If you accept archive formats like zip files on your web application, treat the names of files contained within the archive as untrusted. Attackers will attempt to make use of “zip slip” vulnerabilities by generating filenames with relative path syntax.
* If you are storing a lot of file uploads consider using a
*Content Delivery Network* (CDN). Storing uploaded content with a third party removes the risk of arbitrary file writes.
* You should store uploaded files on your server in a separate directory from running code, and preferably in a separate disk partition. Make sure you web-server process has only the permissions it needs to function – it shouldn’t be able to overwrite any files in the code directory at runtime.
* It’s a good idea to validate file types when they are uploaded, and to set a maximum file size.
* Running up-to-date virus scanning software on your servers will help you spot malicious uploads.

## CWEs

* [CWE-434](https://cwe.mitre.org/data/definitions/434.html)

About ShiftLeft

ShiftLeft empowers developers and AppSec teams to dramatically reduce risk by quickly finding and fixing the vulnerabilities most likely to reach their applications and ignoring reported vulnerabilities that pose little risk. Industry-leading accuracy allows developers to focus on security fixes that matter and improve code velocity while enabling AppSec engineers to shift security left.

A unified code security platform, ShiftLeft CORE scans for attack context across custom code, APIs, OSS, containers, internal microservices, and first-party business logic by combining results of the company’s and Intelligent Software Composition Analysis (SCA). Using its unique graph database that combines code attributes and analyzes actual attack paths based on real application architecture, ShiftLeft then provides detailed guidance on risk remediation within existing development workflows and tooling. Teams that use ShiftLeft ship more secure code, faster. Backed by SYN Ventures, Bain Capital Ventures, Blackstone, Mayfield, Thomvest Ventures, and SineWave Ventures, ShiftLeft is based in Santa Clara, California. For information, visit: www.shiftleft.io.

Share

See for yourself – run a scan on your code right now