Protecting against directory traversal

1.1k views Asked by At

newbie here, int the following the it takes in a file as a parameter and concatenates it to the directory string, it then looks for the file and using streams fetches and serves the file to the browser for downloading. This code is susceptible to directory traversal and im not sure how to go about hardening the code to counteract this.

<%
         if(request.getParameter("file")!=null)
        {
            String context = request.getContextPath();

            int BUFSIZE = 4096;
               String filePath;


            filePath = request.getParameter("file");
            File file = new File(getServletContext().getRealPath("/") +context);
            file = new File(file.getParent()+"/documents/"+filePath);       
            int length   = 0;
            ServletOutputStream outStream = response.getOutputStream();
            //response.setContentType("text/html");
            response.setContentLength((int)file.length());
            String fileName = (new File(filePath)).getName();
            response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

            //response.setHeader("Content-Disposition", "attachment; filename=\"" +new Random().nextInt(10000)+ "\"");

            byte[] byteBuffer = new byte[BUFSIZE];
            DataInputStream in = new DataInputStream(new FileInputStream(file));

            while ((in != null) && ((length = in.read(byteBuffer)) != -1))
            {
            outStream.write(byteBuffer,0,length);
            }

            in.close();
            outStream.close();
        }
        else
        {

        }

%>

1

There are 1 answers

0
SPoint On

The problem consist of the creation of the outputFile with a non trusted filename. Validate the filename will solve your PathTraversal.

Example of a remediation :

if (validateFileName(request.getParameter("file")));
     filePath = request.getParameter("file");
else
// Error 


//....
//.....

boolean validateFilename(String fileName)
      {
            // This represents the format /myapp/temp/<filename>
            String goodPattern = "/myapp/temp/(\\w|\\s|\\.|-|){1,20}";
            File file = new File (fileName);
            Pattern p = Pattern.compile(goodPattern);
            Matcher m = p.matcher(file.getCanonicalPath());
            if (!m.matches())
            {
                  return false;
            }
            return true;
      }

See: