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