From 236bf03544b5d1d74866e08811b9cc5897df8d4b Mon Sep 17 00:00:00 2001 From: Jose Fernandez Date: Wed, 12 May 2021 10:50:34 -0700 Subject: [PATCH 1/3] Block requests with duplicate Host headers --- .../netty/server/ClientRequestReceiver.java | 16 ++++++++-- .../server/ClientRequestReceiverTest.java | 29 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java b/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java index b03e76b9dd..9ad24ec797 100644 --- a/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java +++ b/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java @@ -21,7 +21,6 @@ import static com.netflix.netty.common.HttpLifecycleChannelHandler.CompleteReason.SESSION_COMPLETE; import static com.netflix.zuul.netty.server.http2.Http2OrHttpHandler.PROTOCOL_NAME; -import com.netflix.netty.common.HttpLifecycleChannelHandler; import com.netflix.netty.common.SourceAddressChannelHandler; import com.netflix.netty.common.ssl.SslHandshakeInfo; import com.netflix.netty.common.throttle.RejectionUtils; @@ -159,6 +158,19 @@ private void channelReadInternal(final ChannelHandlerContext ctx, Object msg) th ZuulStatusCategory.FAILURE_CLIENT_BAD_REQUEST); zuulRequest.getContext().setError(ze); zuulRequest.getContext().setShouldSendErrorResponse(true); + } else if (zuulRequest.getHeaders().getAll(HttpHeaderNames.HOST.toString()).size() > 1) { + LOG.debug( + "Duplicate Host headers. clientRequest = {} , uri = {}, info = {}", + clientRequest.toString(), + clientRequest.uri(), + ChannelUtils.channelInfoForLogging(ctx.channel())); + final ZuulException ze = new ZuulException("Duplicate Host headers"); + ze.setStatusCode(HttpResponseStatus.BAD_REQUEST.code()); + StatusCategoryUtils.setStatusCategory( + zuulRequest.getContext(), + ZuulStatusCategory.FAILURE_CLIENT_BAD_REQUEST); + zuulRequest.getContext().setError(ze); + zuulRequest.getContext().setShouldSendErrorResponse(true); } handleExpect100Continue(ctx, clientRequest); @@ -206,7 +218,7 @@ public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exc } if (reason == CompleteReason.PIPELINE_REJECT && zuulRequest != null) { - StatusCategoryUtils.setStatusCategory(zuulRequest.getContext(), ZuulStatusCategory.FAILURE_CLIENT_PIPELINE_REJECT); + StatusCategoryUtils.setStatusCategory(zuulRequest.getContext(), ZuulStatusCategory.FAILURE_CLIENT_PIPELINE_REJECT); } if (reason != SESSION_COMPLETE && zuulRequest != null) { diff --git a/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java b/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java index 425729ec26..30f7f42279 100644 --- a/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java +++ b/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java @@ -200,6 +200,35 @@ public void maxHeaderSizeExceeded_setBadRequestStatus() { ZuulStatusCategory.FAILURE_CLIENT_BAD_REQUEST); } + @Test + public void duplicateHostHeader_setBadRequestStatus() { + ClientRequestReceiver receiver = new ClientRequestReceiver(null); + EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestEncoder()); + PassportLoggingHandler loggingHandler = new PassportLoggingHandler(new DefaultRegistry()); + + // Required for messages + channel.attr(SourceAddressChannelHandler.ATTR_SERVER_LOCAL_PORT).set(1234); + channel.pipeline().addLast(new HttpServerCodec()); + channel.pipeline().addLast(receiver); + channel.pipeline().addLast(loggingHandler); + + HttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/post"); + httpRequest.headers().add("Host", "foo.bar.com"); + httpRequest.headers().add("Host", "bar.foo.com"); + + channel.writeOutbound(httpRequest); + ByteBuf byteBuf = channel.readOutbound(); + channel.writeInbound(byteBuf); + channel.readInbound(); + channel.close(); + + HttpRequestMessage request = ClientRequestReceiver.getRequestFromChannel(channel); + SessionContext context = request.getContext(); + assertEquals(StatusCategoryUtils.getStatusCategory(context), + ZuulStatusCategory.FAILURE_CLIENT_BAD_REQUEST); + assertEquals("Duplicate Host headers", context.getError().getMessage()); + } + @Test public void setStatusCategoryForHttpPipelining() { From c1b0b5f9b7a96b56c2e4ea8cca5e517f42e49188 Mon Sep 17 00:00:00 2001 From: Jose Fernandez Date: Wed, 12 May 2021 11:17:44 -0700 Subject: [PATCH 2/3] Remove redundant clientRequest.toString() --- .../com/netflix/zuul/netty/server/ClientRequestReceiver.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java b/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java index 9ad24ec797..c85031fb4d 100644 --- a/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java +++ b/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java @@ -132,7 +132,7 @@ private void channelReadInternal(final ChannelHandlerContext ctx, Object msg) th if (clientRequest.decoderResult().isFailure()) { LOG.warn( "Invalid http request. clientRequest = {} , uri = {}, info = {}", - clientRequest.toString(), + clientRequest, clientRequest.uri(), ChannelUtils.channelInfoForLogging(ctx.channel()), clientRequest.decoderResult().cause()); @@ -161,7 +161,7 @@ private void channelReadInternal(final ChannelHandlerContext ctx, Object msg) th } else if (zuulRequest.getHeaders().getAll(HttpHeaderNames.HOST.toString()).size() > 1) { LOG.debug( "Duplicate Host headers. clientRequest = {} , uri = {}, info = {}", - clientRequest.toString(), + clientRequest, clientRequest.uri(), ChannelUtils.channelInfoForLogging(ctx.channel())); final ZuulException ze = new ZuulException("Duplicate Host headers"); From 72bce0d0d141659a11f535b6ee3f903e6954ec3b Mon Sep 17 00:00:00 2001 From: Jose Fernandez Date: Wed, 26 May 2021 13:18:04 -0700 Subject: [PATCH 3/3] Change error wording from Duplicate to Multiple --- .../com/netflix/zuul/netty/server/ClientRequestReceiver.java | 4 ++-- .../netflix/zuul/netty/server/ClientRequestReceiverTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java b/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java index c85031fb4d..02fce09afa 100644 --- a/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java +++ b/zuul-core/src/main/java/com/netflix/zuul/netty/server/ClientRequestReceiver.java @@ -160,11 +160,11 @@ private void channelReadInternal(final ChannelHandlerContext ctx, Object msg) th zuulRequest.getContext().setShouldSendErrorResponse(true); } else if (zuulRequest.getHeaders().getAll(HttpHeaderNames.HOST.toString()).size() > 1) { LOG.debug( - "Duplicate Host headers. clientRequest = {} , uri = {}, info = {}", + "Multiple Host headers. clientRequest = {} , uri = {}, info = {}", clientRequest, clientRequest.uri(), ChannelUtils.channelInfoForLogging(ctx.channel())); - final ZuulException ze = new ZuulException("Duplicate Host headers"); + final ZuulException ze = new ZuulException("Multiple Host headers"); ze.setStatusCode(HttpResponseStatus.BAD_REQUEST.code()); StatusCategoryUtils.setStatusCategory( zuulRequest.getContext(), diff --git a/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java b/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java index 30f7f42279..bf043992ef 100644 --- a/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java +++ b/zuul-core/src/test/java/com/netflix/zuul/netty/server/ClientRequestReceiverTest.java @@ -201,7 +201,7 @@ public void maxHeaderSizeExceeded_setBadRequestStatus() { } @Test - public void duplicateHostHeader_setBadRequestStatus() { + public void multipleHostHeaders_setBadRequestStatus() { ClientRequestReceiver receiver = new ClientRequestReceiver(null); EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestEncoder()); PassportLoggingHandler loggingHandler = new PassportLoggingHandler(new DefaultRegistry()); @@ -226,7 +226,7 @@ public void duplicateHostHeader_setBadRequestStatus() { SessionContext context = request.getContext(); assertEquals(StatusCategoryUtils.getStatusCategory(context), ZuulStatusCategory.FAILURE_CLIENT_BAD_REQUEST); - assertEquals("Duplicate Host headers", context.getError().getMessage()); + assertEquals("Multiple Host headers", context.getError().getMessage()); } @Test