From 59a80ea0179cb5b1483611093182250bec540b8d Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 21 Apr 2009 04:34:48 +0000 Subject: [PATCH] 273011 XSS in directory listing git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@166 7e9141cc-0065-0410-87d8-b60c137991c4 --- VERSION.txt | 2 +- .../jetty/security/IdentityService.java | 7 +- .../eclipse/jetty/servlet/ServletHandler.java | 2 - .../jetty/servlet/DefaultServletTest.java | 104 ++++++++++++++++++ .../java/org/eclipse/jetty/util/URIUtil.java | 30 +++-- .../eclipse/jetty/util/resource/Resource.java | 16 ++- .../java/org/eclipse/jetty/util/URITest.java | 3 + 7 files changed, 146 insertions(+), 18 deletions(-) create mode 100644 jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java diff --git a/VERSION.txt b/VERSION.txt index efe57fbc329..d2296484ca2 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -5,7 +5,7 @@ jetty-7.0.0.M1-SNAPSHOT + JETTY-695 Handler dump + Reworked authentication for deferred authentication + JETTY-983 DefaultServlet generates accept-ranges for cached/gzip content - + + 273011 JETTY-980 JETTY-992 Security / Directory Listing XSS present jetty-7.0.0.M0 + JETTY-496 Support inetd/xinetd through use of System.inheritedChannel() diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java index 7cea4225a1c..00d908c4138 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java @@ -30,8 +30,11 @@ public interface IdentityService /* ------------------------------------------------------------ */ /** - * Scope the {@link UserIdentity} to a {@link UserIdentity.Scope}. - * @param user The current user or null for no user associated. + * Associate a user identity with the current thread. + * This is called with as a thread enters the + * {@link SecurityHandler#handle(String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)} + * method and then again with a null argument as that call exits. + * @param user The current user or null for no user to associated. */ void associate(UserIdentity user); diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java index ad05d458e6a..c53d59fad23 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java @@ -312,10 +312,8 @@ public class ServletHandler extends AbstractHandler // Get the base requests final Request base_request=(request instanceof Request)?((Request)request):HttpConnection.getCurrentConnection().getRequest(); - final String old_servlet_name=base_request.getServletName(); final String old_servlet_path=base_request.getServletPath(); final String old_path_info=base_request.getPathInfo(); - UserIdentity scoped_identity = null; DispatcherType type = base_request.getDispatcherType(); Object request_listeners=null; diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java new file mode 100644 index 00000000000..001f5711189 --- /dev/null +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java @@ -0,0 +1,104 @@ +package org.eclipse.jetty.servlet; + +import java.io.File; + +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; + +import org.eclipse.jetty.server.LocalConnector; +import org.eclipse.jetty.server.Server; + +public class DefaultServletTest extends TestCase +{ + private Server server; + private LocalConnector connector; + private ServletContextHandler context; + + protected void setUp() throws Exception + { + super.setUp(); + + server = new Server(); + server.setSendServerVersion(false); + + connector = new LocalConnector(); + + context = new ServletContextHandler(); + context.setContextPath("/context"); + context.setWelcomeFiles(new String[] {}); // no welcome files + + server.setHandler(context); + server.addConnector(connector); + + server.start(); + } + + protected void tearDown() throws Exception + { + super.tearDown(); + + if (server != null) + { + server.stop(); + } + } + + public void testListingXSS() throws Exception + { + ServletHolder defholder = context.addServlet(DefaultServlet.class,"/*"); + defholder.setInitParameter("dirAllowed","true"); + defholder.setInitParameter("redirectWelcome","false"); + defholder.setInitParameter("gzip","false"); + + File resBase = new File("src/test/resources"); + + assertTrue("resBase.exists",resBase.exists()); + assertTrue("resBase.isDirectory",resBase.isDirectory()); + + String resBasePath = resBase.getAbsolutePath(); + defholder.setInitParameter("resourceBase",resBasePath); + + StringBuffer req1 = new StringBuffer(); + req1.append("GET /context/org/mortbay/resource/; HTTP/1.1\n"); + req1.append("Host: localhost\n"); + req1.append("\n"); + + String response = connector.getResponses(req1.toString()); + + assertResponseContains("org/mortbay/resource/one/",response); + assertResponseContains("org/mortbay/resource/two/",response); + assertResponseContains("org/mortbay/resource/three/",response); + + assertResponseNotContains(""); + assertEquals("/context/%27list%27/%22me%22/%3B%3Cscript%3Ewindow.alert(%27xss%27)%3B%3C/script%3E", buf.toString()); } /* ------------------------------------------------------------ */