# 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 Java

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 Java snippet shows a profile photo upload function that takes the filename from a multipart form request:

“`java
@MultipartConfig
public class UnsafeUploadServlet extends HttpServlet
{
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
final String path = “/var/tmp/photo”;/**
* Taking the filename from the HTTP request is dangerous – an attacker
* can override any file they wish in the directory, and in this case,
* they can use the “../” syntax in a filename to climb out of the
* intended directory.
*/
final Part filePart = request.getPart(“file”);
final String fileName = getFileName(filePart);

OutputStream out = null;
InputStream content = null;

try
{
out = new FileOutputStream(path + File.separator + fileName);
content = filePart.getInputStream();

int read;
final byte[] bytes = new byte[1024];

while ((read = content.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
}
catch (FileNotFoundException error)
{
throw new ServletException(“Unable to create profile photo on disk”, error);
}
finally
{
if (out != null) {
out.close();
}
if (content != null) {
content.close();
}
}

response.sendRedirect(“/photo”);
}

private String getFileName(final Part part)
{
for (String content : part.getHeader(“content-disposition”).split(“;”)) {
if (content.trim().startsWith(“filename”)) {
return content.substring(content.indexOf(‘=’) + 1).trim().replace(“\””, “”);
}
}

return null;
}
}
“`

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 constructor of the `FileOutputStream` class. This will allow 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:

“`java
final String path = “/var/tmp/photo”;
final Part filePart = request.getPart(“file”);
final String fileName = getFileName(filePart);/**
* Removing anything except alphanumeric characters (and periods) will
* stop the file being written in an arbitrary directory – but it will
* still allow files in a given directory to be overwritten.
*/
final String safeFileName = fileName.replaceAll(“[^a-zA-Z0-9\\.]”, “_”);
“`

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:

“`java
final String path = “/var/tmp/photo”;/**
* The safest method is to not take any part of the filename from the
* HTTP request at all – simply name the file for what it is for
* (e.g. the user’s name) or generate a random name.
*/
String safeFileName = UUID.randomUUID() + “.jpg”;
“`

## 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