tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Hans Bergsten <h...@gefionsoftware.com>
Subject DefaultServlet path checks
Date Sat, 06 Nov 1999 22:52:57 GMT
I believe I've found a solution for checking the path in the DefaultServlet
that works with both 8.3 and long file paths on Windows and symbolic links
on Unix, and still catches all attempts to get to the source of JSP files
or other extension mapped files. I have only tested this on Windows but I
don't see why it shouldn't work on other platforms.

The solution is to always check for ".." and then only compare the file 
extension part of the URI with with the file extension from the canonical 
path. As far as I can tell, that's the only part we need to worry about
since that's where extra characters or mixed case can fool the container
to dispatch to DefaultServlet instead of a servlet mapped to the file
extension. Mixed case in the path itself doesn't really matter; on a case
sensitive platform the file will not be found, on a case insensitive it
will be found but that's okay as long as we catch tricks with the extension
part.

Please take a look at this version of the serveFile() method. If everyone
is happy with it, I will commit it to both the J2EE branch and the main
branch.

    private void serveFile(File file, HttpServletRequest request,
        HttpServletResponse response) throws IOException {

    	String absPath = file.getAbsolutePath();
	    String canPath = file.getCanonicalPath();
		if(absPath.indexOf("..") != -1) {
			// We have .. in the path...
	    	response.sendError(response.SC_NOT_FOUND,
	    	    "File Not Found:<br>" + absPath);
	    	return;
		}

        // Compare the file extension part of the requested name
        // with the "real" extension, to catch attempts to read
        // shtml or jsp source by adding characters or using mixed
        // case extension on Windows platforms
        String reqExt = absPath;
        int dot = absPath.lastIndexOf('.');
        if (dot != -1 && dot < absPath.length() - 1) {
            reqExt = absPath.substring(dot + 1);
        }
        String canExt = canPath;
        dot = canPath.lastIndexOf('.');
        if (dot != -1 && dot < canPath.length() - 1) {
            canExt = canPath.substring(dot + 1);
        }
        if (!canExt.equals(reqExt)) {
	    	response.sendError(response.SC_NOT_FOUND,
	    	    "File Not Found:<br>" + absPath);
	    	return;
        }

    	String mimeType = mimeTypes.getContentTypeFor(file.getName());

    	if (mimeType == null) {
    	    mimeType = "text/plain";
    	}

    	response.setContentType(mimeType);
    	response.setContentLength((int)file.length());
    	response.setDateHeader("Last-Modified", file.lastModified());

    	FileInputStream in = new FileInputStream(file);

    	try {
    	    serveStream(in, request, response);
    	} catch (FileNotFoundException e) {
    	    // Figure out what we're serving

    	    String requestURI = (String)request.getAttribute(
    		Constants.Attribute.RequestURI);

       	    if (requestURI == null) {
    	    	requestURI = request.getRequestURI();
    	    }

    	    response.sendError(response.SC_NOT_FOUND,
                    "File Not Found<br>" + requestURI);
    	} catch (SocketException e) {
    	    return;  // munch
    	} finally {
    	    if (in != null) {
    		in.close();
    	    }
    	}
    }


-- 
Hans Bergsten		hans@gefionsoftware.com
Gefion Software		http://www.gefionsoftware.com

Mime
View raw message