[ale] tomcat security problem

Master Wizard mainwizard at vei.net
Wed Feb 13 14:51:19 EST 2002


As part of a security audit for an out-of-state client, I created a jsp 
that can browse a server when executed. The file is attached. I have not 
included the upload functionality, but it is possible.

I am making the following assumptions:
1. On *nix, the jsp runs with the permissions of the JVM, which runs 
with the permissions of tomcat.
2. Any jsp container will have the same problem.

My big concern is that, in a hosting environment with the ability to run 
jsp's, user a could run this kind of jsp and browse or hack into user 
b's files.

Can tomcat be set up to restrict access of a jsp/servlet to certain 
directories based on which directory it is in or which URL was used to 
access it?

On a *nix system, damage will be limited by permissions, but on a Win* 
system?

Any tips/hints/help would be appreciated.
Ed.


<%@page import="java.io.*"%>
<%@page import="java.util.*"%>
<%!
String adjustPath(String path)
{
  //Required by windows as they use the escape character as the file separator
  StringBuffer sb = new StringBuffer("");
  StringTokenizer st = new StringTokenizer(path, "\\");
  while(st.hasMoreTokens())
  {
    sb.append(st.nextToken() + "\\\\");
  }
  path = sb.toString();
  if(path.endsWith("\\\\"))
  {
    path = path.substring(0, path.length() - 2);
  }
  return path;
}
%>
<%
String auditDir = "";
String thisJSP = request.getRequestURI();
//Some browsers might not be setup to recognize all file extension mime types.
//Explicitly set those here.
String[] binaryFiles = {".exe", ".com"};
String[] zipFiles = {".jar", ".zip"};
boolean contentSet = false;
auditDir = request.getParameter("DirName");
System.out.println("Audit dir = " + auditDir);
if(auditDir == null || "".equalsIgnoreCase(auditDir))
{
  auditDir = application.getRealPath("/");
}
File f = null;
f= new File(auditDir);
if (f.isDirectory())
{
%>
  <html>
  <head><title>Security Audit</title>
  <SCRIPT language='JavaScript'>
  function newPage(path)
  {
    document.audit.DirName.value=path;
    document.audit.submit.click();
  }
  </SCRIPT>
  </head>
  <body>
  <FORM name="audit" action='<%=thisJSP %>' method=post>
  <INPUT type=textbox size='50' name='DirName' value="<%=auditDir %>">
  <INPUT type=submit name='submit' value='Open'>
  </FORM>
<%
  out.println("found directory " + f.toString() + "<BR>");
  File[] files = f.listFiles();
  for (int i=0; i < files.length; i++)
  {
    out.println("<br>");
    if(files[i].isDirectory())
    {
%>
      <a onClick="newPage('<%=adjustPath(files[i].toString()) %>')" href=''>
        <font color='blue'><%=files[i] %></font>
      </a>
<%
    }
    else
    {
%>
      <a onClick="newPage('<%=adjustPath(files[i].toString()) %>')" href=''>
        <font color='purple'><%=files[i] %></font>
      </a>
<%
    }
  }
%>
</body>
</html>
<%
}
else
{
  for(int i = 0; i < zipFiles.length; i++)
  {
    if(f.toString().endsWith(zipFiles[i]))
    {
      response.setContentType("application/x-zip-compressed");
      contentSet = true;
    }
  }
  for(int i = 0; i < binaryFiles.length; i++)
  {
    if(f.toString().endsWith(binaryFiles[i]))
    {
      response.setContentType("application/x-zip-compressed");
      contentSet = true;
    }
  }
  if(!contentSet)
  {
    if(getServletContext().getMimeType(f.toString()) != null)
    {
      response.setContentType(getServletContext().getMimeType(f.toString()));
    }
    else
    {
      response.setContentType("text/html");
    }
  }
  FileInputStream fis = null;
  ServletOutputStream sos = null;
  try
  {
    fis = new FileInputStream(f.toString());
    sos = response.getOutputStream();
    byte[] buf = null;
    buf = new byte[4*1024];
    int bytesRead;
    while((bytesRead = fis.read(buf)) != -1)
    {
      sos.write(buf, 0, bytesRead);
    }
    sos.flush();
    sos.close();
  }
  catch(Exception e)
  {
    System.out.println(e.getMessage());
    e.printStackTrace();
    sos.flush();
    sos.close();
  }
  finally
  {
    sos.close();
  }
}
%>




---
This message has been sent through the ALE general discussion list.
See http://www.ale.org/mailing-lists.shtml for more info. Problems should be 
sent to listmaster at ale dot org.




More information about the Ale mailing list