Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Java based applications, including web applications, that must accept file uploads must ensure that an adversary attacker cannot upload or transfer malicious files. If a restricted file containing code is executed by the target system, it can result in misuse of privilegescompromise application-layer defenses. For example, an application that permits HTML files to be uploaded could allow malicious code to be executed - an executed—an attacker can submit a valid HTML file with a cross-site - scripting (XSS) payload that will execute in the absence of an output-escaping routine. For this reason, many applications restrict the type of files that can be uploaded.

It may also be possible to upload files with dangerous extensions such as .exe and .sh which may that could cause arbitrary code execution on server-side applications.. An application that restricts only the Content-Type field in the HTTP header could be vulnerable to such an attack.

To support file uploadFor providing file upload functionality, a typical Java Server Pages (JSP) page consists of code such as the following:

Code Block
<s:form action="uploadActiondoUpload" method="POST" enctype="multipart/form-data">
  <s:file name="uploadFile" label="Choose File" size="40" />
  <s:submit value="Upload" name="submit" />
</s:form>

Many Java enterprise frameworks provide configuration settings intended to be used as a defense against arbitrary file upload. Unfortunately, most of them fail to provide adequate protection. Mitigation of this vulnerability involves checking file size, content type, and file contents, among other metadata attributes.

Noncompliant Code Example

This noncompliant code example shows some XML code from the upload action of a Struts 2 application.   The interceptor code is responsible for allowing file uploads.

Code Block
<action name="doUpload" class="com.example.UploadAction">
  <interceptor-ref name="fileUploadupload">
    <param name="maximumSize"> 10240 </param>
    <param name="allowedTypes"> text/plain,image/JPEG,text/html </param>
  </interceptor-ref>        
</action>

The code for file upload is present upload appears in the Upload UploadAction class:

Code Block
bgColor#ffcccc
langjava
public class UploadUploadAction extends ActionSupport {
  private File uploadedFile;
  // setter and getter for uploadedFile
  
  public String execute() {
    try {
      // File path and file name are hardcoded for illustration
      File fileToCreate = new File("filepath", "filename");
      // Copy temporary file content to this file
      FileUtils.copyFile(uploadedFile, fileToCreate);
      return "SUCCESS";
    } catch (ExceptionThrowable e) {
      e.printStackTrace();
      addActionError(e.getMessage());
      return "ERROR";
    }
  }
} 

The value of the parameter type maximumSize ensures that a particular Action does not cannot receive a very large file. The allowedType allowedTypes parameter defines the type of files that are accepted. However, this approach does not fails to ensure that the uploaded file conforms to the security requirements as because interceptor checks can be trivially bypassed. If an attacker uses were to use a proxy tool to change the content type in the raw HTTP request in transit, the framework would not fail to prevent the file's upload. Consequently, an attacker can could upload a malicious file having a that has a .exe extension.This code appears to violate ERR08-J. Do not catch NullPointerException or any of its ancestors. But it does not violate that rule, because it falls under the exception ERR08-EX2, for example.

Compliant Solution 

The file upload must succeed only succeed if when the content type matches the actual content present within of the file. For example, a file with an image header must contain only contain an image and must not contain executable code. This compliant solution uses the Apache Tika library  library [Apache 2013to detect and extract metadata and structured text content from documents using existing parser libraries [Apache Tika|http://tika.apache.org/index.html]. The checkMetaData() method must be called before invoking invoking code in execute() that is responsible for uploading the file.

Code Block
bgColor#ccccff
langjava
public class UploadAction extends ActionSupport {
  private File uploadedFile;
  // setter and getter for uploadedFile
  
  public static boolean checkMetaData(File f, String getContentType) {
  InputStream is = null;
  try {
    String execute() {
    try {
      // File path and file name are hardcoded for illustration
      File fileToCreate = new File("filepath", "filename");

      boolean textPlain = checkMetaData(uploadedFile, "text/plain");
      boolean img = checkMetaData(uploadedFile, "image/JPEG");
      boolean textHtml = checkMetaData(uploadedFile, "text/html");

	  if (!textPlain && !img && !textHtml) {
	    return "ERROR";
      }		

	  // Copy temporary file content to this file
      FileUtils.copyFile(uploadedFile, fileToCreate);
      return "SUCCESS";
    } catch (Throwable e) {
      addActionError(e.getMessage());
      return "ERROR";
    }
  }

  public static boolean checkMetaData(
    File f, String getContentType) {
    try (InputStream is = new FileInputStream(f)); {
      ContentHandler contenthandler = new BodyContentHandler();
      Metadata metadata = new Metadata();
      metadata.set(Metadata.RESOURCE_NAME_KEY, f.getName());
      Parser parser = new AutoDetectParser();
      try {
        parser.parse(is, contenthandler, metadata, new ParseContext());
    
  } catch (SAXException | if (metadata.get(Metadata.CONTENT_TYPE).equalsIgnoreCase(getContentType))TikaException e) {
      return true;
 // Handle  }error
    else {
      return false;
      }
  } catch (Exception e) {
    e.printStackTrace();  if (metadata.get(Metadata.CONTENT_TYPE).equalsIgnoreCase(getContentType)) {
    return false;
  } finallyreturn {true;
    if (is !=} null)else {
      try {
 return false;
      is.close();
  }
    } catch (IOException e) {
      //  e.printStackTrace();Handle error
      return }false;
    }
  }
}

The AutoDetectParser selects the best available parser based on the basis of the content type of the file to be parsed.

Applicability

An arbitrary file upload vulnerability could result in privilege escalation and the execution of arbitrary code.

Bibliography

Automated Detection

ToolVersionCheckerDescription
The Checker Framework

Include Page
The Checker Framework_V
The Checker Framework_V

Tainting CheckerTrust and security errors (see Chapter 8)

Bibliography

 

...

Image Modified Image Modified  Image Modified