Merge pull request from GHSA-v7ff-8wcx-gmc5 (#6089)
Always normalize ambiguous URIs Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
parent
d9db52f1d7
commit
d80c622b00
|
@ -1692,7 +1692,8 @@ public class Request implements HttpServletRequest
|
|||
_httpFields = request.getFields();
|
||||
final HttpURI uri = request.getURI();
|
||||
|
||||
if (uri.isAmbiguous())
|
||||
boolean ambiguous = uri.isAmbiguous();
|
||||
if (ambiguous)
|
||||
{
|
||||
UriCompliance compliance = _channel == null || _channel.getHttpConfiguration() == null ? null : _channel.getHttpConfiguration().getUriCompliance();
|
||||
if (uri.hasAmbiguousSegment() && (compliance == null || !compliance.allows(UriCompliance.Violation.AMBIGUOUS_PATH_SEGMENT)))
|
||||
|
@ -1741,7 +1742,15 @@ public class Request implements HttpServletRequest
|
|||
// TODO this is not really right for CONNECT
|
||||
path = _uri.isAbsolute() ? "/" : null;
|
||||
else if (encoded.startsWith("/"))
|
||||
{
|
||||
path = (encoded.length() == 1) ? "/" : _uri.getDecodedPath();
|
||||
// Strictly speaking if a URI is legal and encodes ambiguous segments, then they should be
|
||||
// reflected in the decoded string version. However, it can be ambiguous to provide a decoded path as
|
||||
// a string, so we normalize again. If an application wishes to see ambiguous URIs, then they can look
|
||||
// at the encoded form of the URI
|
||||
if (ambiguous)
|
||||
path = URIUtil.canonicalPath(path);
|
||||
}
|
||||
else if ("*".equals(encoded) || HttpMethod.CONNECT.is(getMethod()))
|
||||
path = encoded;
|
||||
else
|
||||
|
|
|
@ -28,8 +28,11 @@ import javax.servlet.ServletContext;
|
|||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpCompliance;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.http.UriCompliance;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
|
@ -284,6 +287,43 @@ public class WebAppContextTest
|
|||
assertFalse(context.isProtectedTarget("/something-else/web-inf"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProtectedTarget() throws Exception
|
||||
{
|
||||
Server server = newServer();
|
||||
|
||||
HandlerList handlers = new HandlerList();
|
||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||
WebAppContext context = new WebAppContext();
|
||||
Path testWebapp = MavenTestingUtils.getProjectDirPath("src/test/webapp");
|
||||
context.setBaseResource(new PathResource(testWebapp));
|
||||
context.setContextPath("/");
|
||||
server.setHandler(handlers);
|
||||
handlers.addHandler(contexts);
|
||||
contexts.addHandler(context);
|
||||
|
||||
LocalConnector connector = new LocalConnector(server);
|
||||
server.addConnector(connector);
|
||||
connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration().setUriCompliance(UriCompliance.RFC3986);
|
||||
|
||||
server.start();
|
||||
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /test.xml HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.OK_200));
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /%2e/%2e/test.xml HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.OK_200));
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /foo/%2e%2e/test.xml HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.OK_200));
|
||||
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /WEB-INF HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.NOT_FOUND_404));
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /WEB-INF/ HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.NOT_FOUND_404));
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /WEB-INF/test.xml HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.NOT_FOUND_404));
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /web-inf/test.xml HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.NOT_FOUND_404));
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /%2e/WEB-INF/test.xml HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.NOT_FOUND_404));
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /%2e/%2e/WEB-INF/test.xml HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.NOT_FOUND_404));
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /foo/%2e%2e/WEB-INF/test.xml HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.NOT_FOUND_404));
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /%2E/WEB-INF/test.xml HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.NOT_FOUND_404));
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET //WEB-INF/test.xml HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.NOT_FOUND_404));
|
||||
assertThat(HttpTester.parseResponse(connector.getResponse("GET /WEB-INF%2ftest.xml HTTP/1.1\r\nHost: localhost:8080\r\nConnection: close\r\n\r\n")).getStatus(), is(HttpStatus.NOT_FOUND_404));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullPath() throws Exception
|
||||
{
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
test
|
|
@ -0,0 +1 @@
|
|||
test
|
Loading…
Reference in New Issue