users@jersey.java.net

[Jersey] feeding static content

From: Christopher Piggott <cpiggott_at_gmail.com>
Date: Sun, 13 Feb 2011 16:15:19 -0500

I'd like to ask for a peer review of something for security reasons.
I want to feed static resources from jersey, but I want to do it
within jersey rather than adding a separate ServletAdapter. This will
allow me to do some other things, including security-related, weird
manipulation of headers, and, eventually, my own JSP-like filtering.

One thing that concerned me was the idea that somebody could request
"http://me/static/../../../../etc/passwd" (for example) to get a
resource outside of my "root." To protect against this, I compare
what is being requested against my static resource root and I make
sure it's not outside of what I wish to offer. I build the path to
the static resource, then use .getCanonical() to collapse any ..'s,
then compare the paths.

Does anybody see any holes in this?


@Path("/static")
public class StaticResource {
    public final static String STATIC_PATH = "static";
    @GET
    @Path("{what: .*}")
    public Response getStatic(@PathParam("what") String what) throws
FileNotFoundException {
        File root = new File(Application.getMainJarDir(), STATIC_PATH);
        File requestedFile = new File(Hub.getMainJarDir(), STATIC_PATH
+ File.separator + what);

        try {
            requestedFile = requestedFile.getCanonicalFile();
        } catch (IOException e) {
            return Response.status(Status.FORBIDDEN).entity("Not
allowed").build();
        }

        if (!requestedFile.getAbsolutePath().startsWith(root.getAbsolutePath()))
{
            return Response.status(Status.FORBIDDEN).entity("Not
allowed").build();
        }

        ResponseBuilder response;

        try {
            response = Response.ok().entity(new FileInputStream(requestedFile));
        } catch (FileNotFoundException e) {
            response = Response.status(Status.NOT_FOUND).entity("Not found");
        }

        return response.build();
    }
}

--Chris