In the last post, I covered Magic Numbers and how they can be used along with file extensions to validate file uploads. What would happen if you did not restrict the file types you users can upload and picked the wrong location to save them on your server? What if a user uploaded a JSP file?
Let’s first review file uploads. Many web application frameworks, like Struts2 and Spring MVC, make accepting file uploads easy. You simply configure the respective framework and have a form on your page with enctype=”multipart/form-data” along with an input field of type “file”. Under the hood, these frameworks delegate the heavy lifting to the Apache Commons FileUpload component. Then, when a user selects a file on their computer and clicks the submit button, their local file is uploaded to the server hosting the webapp and stored in the configured temp directory. Finally, the respective Controller or Action class that is configured to handle the form submission saves the file to where it will be accessed later.
Many applications like to save uploads where they can later be accessed/served to other users. One location to use is the exploded WAR file directory of your application. If you are using Tomcat, this would be $CATALINA_HOME/webapps/YourWarFile.
Saving your uploaded files in this location and not restricting the types of files a user can upload is very dangerous because a user could upload and execute a JSP file. Once the user accesses their JSP on your server, the application server would execute any code contained in it with the privileges of the system user running the application server.
What code could this JSP execute? The JSP would have access to any Java library available in the application and the standard Java libraries, including java.lang.Runtime. As you may recall, with Runtime you can execute and display the output of local system commands from Java with code along the lines of:
<% Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(command); %>
An example command that can be run on Windows is “cmd /c dir” and a similar example on Linux is “ls –l”. Imagine the possibilities if the application server was running as root!
It is a good idea to limit the types of files you application accepts and do not accept JSP files. Also, carefully consider where uploaded files are ultimately stored. Finally, run your application server with a low privileged user that has the minimal system access required to perform the job.